I'm trying to touch a UITextField using Calabash. When I use query("UITextField")[x], where x is the number in the array of text fields that are on screen, I can correctly query for just one text field. However, when I use touch("UITextField")[x] it will always touch the first text field. This happens when using the console and when using cucumber to run the tests.
Here's relevant info about my setup:
xcode-select --print-path
/Applications/Xcode.app/Contents/Developer
xcodebuild -version
Xcode 7.2
Build version 7C68
calabash-ios version
0.16.4
Try
touch("UITextField index:x")
where x == your index.
Also, please update to calabash 0.17.0 :)
Explanation
The Calabash environment is composed of a client and a server. The server runs on the device/simulator as part of the app and receives commands/queries from the client. In this case, the client is the ruby interface through which you are interacting with the app.
The client is responsible for sending enough info to the server to select objects on which to perform the gestures. Once the gestures / queries have been performed, results are sent back to the client as json / hashes, which is what you see in the console. The distinction is important: the server performs the queries, the client does not.
By the time you are seeing the results of a query / gesture in the irb console, it has already been performed: the json that is returned simply represents the state of the views, not the actual views themselves.
So when you are running
touch("UITextField")[index]
This is actually equivalent to
touch_results = touch("UITextField")
touch_results[index]
In the first line, touch_results is receiving the json representation of the elements affected by performing touch on the results of querying for "UITextField", meaning that the touch event has already completed by the time you try to access the results with touch_results[index].
Another way to think about it is this: Given res = touch(query), the query is the part used to specify the actual views, and res is just json that represents the state of those views / results of a query or gesture.
In conclusion
When you need more specificity on a query, the specifiers need to go inside the query. E.g.,
touch("all UIScrollView UITextField marked:'some text' index:2")
(this will search for all UIScrollViews , find any UITextFields inside of them which contain text matching 'some text', and return the 3rd of such results).
For a full explanation of query language syntax, see the docs.
Related
I have created a scenario where I iterate through multiple modules with an array of data. This works fine.
After this completes, I want to run a module once before the scenario completes.
How do I add a module that won't get called in the loop?
There are few ways to achieve this,
Use Router to Create a new Route that will be triggered after the
first route is complete
Trigger new Scenario via Webhooks after you are done with the
scenario
If you are working with array, then using Array Aggregator or other
Aggregators will allow you to first complete the iteration and then
trigger the module you want to use
I am not sure exactly what you want to do after the iteration is complete, but setting the scenarios as displayed in the screenshot below should help you get started on this,
Using Router
For this you can create a router, the upper hand of the router is always executed first, so the iterator and other operations will be done there. After which, the next hand/route will be executed which will be the module you want to trigger at last.
However, If you want to pass some values from the first hand/route to the last one then you will need to set a variable and fetch it on the second route. See details here : https://www.integromat.com/en/help/converger
Using Aggregator Module
You can either use Array, Text or Numeric Aggregator to aggregate all the iteration operations and then trigger the module that you want to use at last.
As far as my knowledge goes, there is no Integromat default modules that can be configured before the scenario ends. We can leverage the Integromat API in future that is currently in development to do so.
I found a filter to be the most easy way of doing this. Essentially chekcing if this bundle position is equal to the total number of bundles!
If you're interested in doing something on the last iteration only, you can use a filter to check if the current bundle is equal to the total number of bundles
last bundle filter
They won't let me paste pics sigh
I have an application that uses a combination of ContentService.Saved & ContentService.Saving to extend Umbraco to manage content.
I have two websites in one Umbraco installation I am using those methods to keep content up to date in different parts of the tree.
So far I have got everything working the way I wanted to.
Now I want to add a feature that: depending on which Umbraco User is logged in, will either publish the content or simply send it for approval.
So I have changed some lines of code from:
cs.SaveAndPublishWithStatus(savedNode, 0, false)
To this:
cs.SendToPublication(savedNode);
Now the problem that I am finding is that unlike the SaveAndPublishWithStatus() method, the cs.SendToPublication(); doesn't have the option of passing false so that a save event is not raised. So I get into an infinite loop.
When I attach the debugger and manually stop the infinite loop the first time it calls cs.SendToPublication(savedNode); I get exactly the behavior I want.
Any ideas about how I can get round this problem? Is there a different method that I should be using?
You are correct in saying that it currently isn't possible to set raiseEvents to false when sending an item to publication - that's a problem.
I've added that overload in v. 7.6 (http://issues.umbraco.org/issue/U4-9490).
However considering that you need this now, an interim solution could be that you make sure your code is only run once when triggered by the .Saved / .Saving events.
One way to do this would be to check the last saved date (UpdateDate) in your code. If the content was saved within the last second of the current save operation, you know that this is a save event triggered by the save happening in SendToPublication action. Then you also know that the item has already been sent to publication and that this doesn't need to be done again - thereby preventing the endless loop from happening.
I am writing UI automation tests for an iOS native app using Appium and gradually realizing how most of the element locating strategies don't reliably work for iOS. Apart from XPath which randomly works, other options that I have are:
Accessibility ID (did not work for me)
name (not every element will have value for 'name' attribute)
class (makes sense when you are working with a list of elements)
iOS UiAutomation predicates (steep learning curve for beginners)
I have been trying to understand how to use iOS UiAutomation locator strategy and find elements using it but it's not working on Appium Inspector. I have referred to these documentations (Appium iOS Predicate reference, Apple UIAutomation reference) but I feel they cater to an advanced Appium user audience who have some knowledge on iOS development, not for beginners.
Currently the element hierarchy that I am trying to find element in is something like this:
My current automation setup is:
XCode 6.3.2
Appium 1.4.8
iOS 8.3
Appium Java Client 3.1.0
What will be the locator I can use to locate the highlighted element using UiAutomation predicate strategy? I have been trying a few options on the Appium Inspector like:
applications()[0].windows()[0].navigationBars()[0].textFields().withPredicate("value == 'Search eBay'")
.textFields().withPredicate("value == 'Search eBay'")
These did not work. What am I doing wrong here? Are there any other documentations which clearly explain iOS UiAutomation locators from ground-up? It will really help if someone can explain these basics.
I have never worked with Appium before but I have worked with UIAutomation in javascript.
You can probably find the element using:
....textFields().firstWithName("Search eBay")
Note that UIAuatomation uses UIAccessibility protocol. The value for UITextField is its accessibilityValue and that one will be equal to the searched text, not the placeholder. Once you type something to the field, you will be able to use value.
Of course, in your case grabbing the first text field would work too, as there is only one in the navigation bar.
Just use this .navigationsBars()["EBUH_whateverstring"].textfields()["Search eBay"].textfields()["Search eBay"].
Better way is to ask dev to add accessibility id in case the code is in Obj-C or accessibility identifier if the app code is in Swift. Otherwise if the passed on element value is dynamic then the test will fail in asserting or doing action upon this element.
Another failsafe method is using array values.
.navigationsBars()[0].textfields()[0].textfields()[0] --> Check the array values of your element is [0] or any other. U can use this appium app to get the array value from where it shows xpath value for the element. Or you can use XCode Instruments if you have access to the code to find the exact value as UIAutomation interprets it.
If you are trying to find elements in Appium you will have to write code to do so. Assuming you are using Java, which is what I am using for code, the way you locate these elements is through the driver, tables, and rows.
What do I mean by this? Each element has an XPath associated with it, so one way of doing this is saying
driver.findElementByXPath("xpath_string_here");
This can be very useful when trying to run assertions, for example. using the above code, let us say we want to assert that its name is valid. we can say:
AssertEquals(driver.findElementByXPath("xpath_string_here").getAttribute("name"), 'Practice Example");
When I mention tables and rows, I mean doing something like this:
MobileElement table = (MobileElement) driver.findElementByXPath("string here");
List<WebElement> rows = driver.findElementByClassName("Class name here");
What does this code do? it creates a variable of type MobileElement which will go through the xPath you want, and then the rows value will find elements of that class name present inside of that table view. So in the above image, I would stop at the XPath for the UIAWindow, and then tell my rows to find the elements using class name of "UIAButton" for example.
At this point it is a matter of a simple loop if you want to run some actions on them such as .click(); using their indexes using the .get(int i) method. So for example: rows.get(i).click();
Does this help you with your question?
FitNesse .Net (using the FIT test system, not SLIM) supports testing for lists of the form:
element1, element2, ..., elementN
This works well. However, I can't figure out how to test for an empty list.
Empty strings can be tested for with blank. What's the equivalent for a list?
Try this:
|configure|processor|add operator|parsequotedstring|
|check|myemptylist|""|
Please see here: https://github.com/imanushin/NetRunner/wiki/Collection-result
If there will be any collection on output NetRunner (and fitSharp) will write several red rows (e.g. test will fail).
For example, by using such functions I'm checking the error entries in the log: the expected entries count is empty list. However, any problematic row will be presented to me on the web page, which is very useful: I collects log results from the several files and story them in the test.
I dont know what exactly i have to type in title for this ,i tried my best
anyway coming to topic
I am making one acc checker for that purpose ,i am sending user and pass from my bsskinedit1 and bsskinedit2
here is my code
s:='http:\\site.com..premlogin='+bsskinedit.text+'&password='+bsskinedit2.text
but it giving some error ,then i used showmessage whats wrong with it then i came with strange result
see below
observer after 4 & and p combining together and appearing as a some new symbol :(
can any one tell me why its coming like this ?
Your code (where you build the URL) is most likely correct (I guess the above has some typos?!), but when you display the URL in a label for instance, the & character is treated as indicator for an accelerator key.
By Windows design, accelerator keys
enable the user to access a menu
command from the keyboard by pressing
Alt along the appropriate letter,
indicated in your code by the
preceding ampersand (&). The character
after the and sign (&) appears
underlined in the menu.
If you want to display the & character itself, you have to set your string variable to &&.
By placing two ampesands together - you state that the character following the first one is not used as the accelerator - rather you actually want to get it (only one) displayed.
Just use your debugger if you want to see the real value that your string variables have, don't output them to a message box or the like... It may have side effects, as you can see.
Regarding the URL you build: I can't possibly know how it has to be correctly, but at least you should use the right slashes!
s := 'http://site.com...'
(All quotes from delphi.about.com)
In addition to what Mef said, you can use OutputDebugString to add your string to the event log in its raw form, so you don't need to modify it before displaying it. Delphi should capture those strings automatically if you're running from the debugger. If you aren't running it from Delphi you can use DebugView instead, which captures the messages from any running applications.