Get all options from Android Spinner using Appium - appium

I am trying to pull all the options off an android spinner, using Appium. With Selenium, you can use the Select object and do something like getOptions (I forget the exact syntax). I need the text from all the options in the spinner.

Considering the spinner options are accessible through Appium. Getting all the values of the options on the spinner shall work as follows :
List<WebElement> spinnerList = driver.findElements(getBy("identifier")); //where identifier would vary on how you can access the elements
String spinnerListElementText[index]; //e.g. to store Text of all the options
for (int index = 0; index < spinnerList.size(); index++) {
String spinnerListElementText[index] = spinnerList.get(index).getText();
}

In Appium, there are test frameworks called Uiautomator, Uiautomator2 and Espresso, respectively. The thing that you were trying to get is not provided by Uiautomator or Uiautomator2 test frameworks. The only way with those frameworks is to click the spinner and get page source of spinner with visible elements. You could try to use Espresso framework. This is the reason:
Uiautomator: It is a test framework which provides a black-box testing for developers. It means that you can not get internal codes of the application.
Espresso: It is a test framework which provides a grey-box testing for developers. It means that you can get internal codes of the application, find elements which are not visible in the page (off-screen elements).
Try to use Espresso framework in Appium.

Related

Enumerate UISupportedExternalAccessoryProtocols at runtime

I'm using Xamarin.iOS to wrap an Objective-C library for an accessory that connects to iPods and iPhones via the dock connector. I wasted a lot of time trying to get the accessory to work in my test app before I discovered that I was missing values under UISupportedExternalAccessoryProtocols in Info.plist in my test app.
I'd like to prevent others from running into the same problem when they use my wrapper library. Since this is a library, I can't have an Info.plist in my project, right? So I'd like to enumerate the values the caller has for UISupportedExternalAccessoryProtocols so I can give an easy to read message to developers that they're missing values. Is there a way to do this at run time?
Thanks!
Either of these will work to access values in the Info.plist:
var protocolArray = (NSArray)NSBundle.MainBundle.InfoDictionary ["UISupportedExternalAccessoryProtocols"];
Or
var protocolArray = (NSArray)NSBundle.MainBundle.ObjectForInfoDictionary ("UISupportedExternalAccessoryProtocols");
then get the values like so:
for (nuint i = 0; i < protocolArray.Count; i++) {
Console.Write (protocolArray.GetItem<NSString> (i).ToString ());
}
You can use
var values = NSBundle.MainBundle.ObjectForInfoDictionary("UISupportedExternalAccessoryProtocols");
to read the value from Info.plist and see if it contains all the required values.

How to test right-to-left language in iOS XCTest unit tests?

Is there a way to switch an XCTest unit test into the right-to-left mode to test Arabic version of the app where sentences are written from right to left of the screen? My app code logic behaves differently based on language direction. I would like to verify this functionality in a unit test. What I need to do is to switch the app into the right-to-left language mode from an XCTest unit test case.
One can run the app in the right-to-left mode by changing the Scheme's Application language settings to Right-to-left Pseudolanguage. Is there a way to do similar thing in a unit test?
My imperfect solution
I ended up changing semanticContentAttribute of a view under test to .ForceRightToLeft. It does what I need to do. It does not feel like a very clean approach though. Firstly, it only works in iOS 9. Secondly, it looks like I am tinkering with my app views on a low level from the unit test. Instead, I would prefer to switch the whole app's language to right-to-left if it is possible.
class MyTests: XCTestCase {
func testRightToLeft() {
if #available(iOS 9.0, *) {
let view = UIView()
view.semanticContentAttribute = .ForceRightToLeft
// Test code involving the view
}
}
}
There's no easy way to do this right now with testing/UI testing besides passing in environment flags or setting the semanticContentAttribute as you are doing now. Filing a bug to Apple is highly recommended.
You can also change the device language & region in the scheme. This means you'll need separate schemes for the various LTR/RTL tests you want to run:
Xcode even provides pseudo-languages for extra-long string & RTL testing.
You can detect the writing direction via
let writingDirection = UIApplication.sharedApplication().userInterfaceLayoutDirection
switch writingDirection {
case .LeftToRight:
//
case .RightToLeft:
//
default:
break // what now? You are obviously using iOS 11's topToBottom direction…
}
To set different languages and locales on startup this might be a proper solution.
What you are looking for is Automated UI-Testing
This example JavaScript code changes the device orientation for example:
var target = UIATarget.localTarget();
var app = target.frontMostApp();
//set orientation to landscape left
target.setDeviceOrientation(UIA_DEVICE_ORIENTATION_LANDSCAPELEFT);
UIALogger.logMessage("Current orientation now " + app.interfaceOrientation());
//reset orientation to portrait
target.setDeviceOrientation(UIA_DEVICE_ORIENTATION_PORTRAIT);
UIALogger.logMessage("Current orientation now " + app.interfaceOrientation());
For testing, if your layout has changed to RTL or LTR you could try to access specific UI Elements and check their content against an expected content. So here is another example to check the contents of a TableViewCell from the official docs:
The crux of testing is being able to verify that each test has been performed and that it has either passed or failed. This code example runs the test testName to determine whether a valid element recipe element whose name starts with “Tarte” exists in the recipe table view. First, a local variable is used to specify the cell criteria:
var cell = UIATarget.localTarget().frontMostApp().mainWindow() \
.tableViews()[0].cells().firstWithPredicate("name beginswith 'Tarte'");
Next, the script uses the isValid method to test whether a valid element matching those criteria exists in the recipe table view.
if (cell.isValid()) {
UIALogger.logPass(testName);
} else {
UIALogger.logFail(testName);
}
If a valid cell is found, the code logs a pass message for the testName test; if not, it logs a failure message.
Notice that this test specifies firstWithPredicate and "name
beginsWith 'Tarte'". These criteria yield a reference to the cell for
“Tarte aux Fraises,” which works for the default data already in the
Recipes sample app. If, however, a user adds a recipe for “Tarte aux
Framboises,” this example may or may not give the desired results.
If you want to test a specific scheme:
Executing an Automation Instrument Script in Xcode
After you have created your customized Automation template, you can execute your test script from Xcode by following these steps:
Open your project in Xcode.
From the Scheme pop-up menu (in the workspace window toolbar), select Edit Scheme for a scheme with which you would like to use your script.
Select Profile from the left column of the scheme editing dialog.
Choose your application from the Executable pop-up menu.
Choose your customized Automation Instrument template from the Instrument pop-up menu.
Click OK to approve your changes and dismiss the scheme editor dialog.
Choose Product > Profile.
Instruments launches and executes your test script.

How does phoneGap (Cordova) work internally, iOS specific

I have started developing html applications for mutliple platforms. I recently heard about Cordova 2.0(PhoneGap) and ever since I have been curious to know how the bridge works.
After lot of code walking, i saw that the Exec.js is the code where call from JS -> Native happens
execXhr = execXhr || new XMLHttpRequest();
// Changeing this to a GET will make the XHR reach the URIProtocol on 4.2.
// For some reason it still doesn't work though...
execXhr.open('HEAD', "file:///!gap_exec", true);
execXhr.setRequestHeader('vc', cordova.iOSVCAddr);
if (shouldBundleCommandJson()) {
execXhr.setRequestHeader('cmds', nativecomm());
}
execXhr.send(null);
} else {
execIframe = execIframe || createExecIframe();
execIframe.src = "gap://ready";
But want to understand how that works, what is the concept here, what does file:///!gap_exec or gap://ready do? and how does the call propgate to the lower layers (native code layers)
thanks a bunch in advance.
The trick is easy:
There is a webview. This displays your app. The webview will handle all navigation events.
If the browser navigates to:
file:///!gap_exec
or
gap://
the webview will cancel the navigation. Everything behind these strings is re-used as an identifier, to get the concrete plugin/plugin-method and parameter:
pseudo-url example:
gap://echoplugin/echothistext?Hello World
This will cause phonegap to look for an echoplugin and call the echothistext method to send the text "Hello World" to the (native) plugin.
update
The way back from native to javascript is (or may be) loading a javascript: url into the webview.
The concrete implementation is a little bit more complex, because the javascript has to send a callback-id to native code. There could be more than one native call are running at the same time. But in fact this is no magic at all. Just a number to get the correct JSON to the right javascript-callback.
There are different ways to communicate between the platform and javascript. For Android there are three or four different bridges.
I am trying to figure this out in more detail, too. Basically there are 2 Methods on the iOS side that can help ...
- webView:shouldStartLoadWithRequest:navigationType: and
- stringByEvaluatingJavaScriptFromString:script
From the sources it seems cordova sends a "READY" message using webView:shouldStartLoadWithRequest:... and then picks up results with the second message, but I am not sure.
Cordova Sources iOSExec
There is much to learn there.

How to find that current Blackberry device support Hindi(or Gujarathi) or not?

Hi blackberry developers,
I am implemented one application targeted to OS6 and above.
Here i am loading url which is contain some Indian (Gujarathi) language into the browserField.
Here My problem is that text displaying some devices correctly but not all.
it is showing text properly in Bold 9780 OS6, But Tourch 9800 OS7 is not showing properly.It is showing only Rectangular Boxes.
So i need to know that is my devise support gujarathi language are not first.
I am using some code to get list of available languages
Locale []loc1=Locale.getAvailableInputLocales();
for(int i=0;i<loc1.length;i++)
{
System.out.println("=====1: "+loc1[i].getLanguage()+"======"+loc1[i].getDisplayLanguage());
RichTextField rh1=new RichTextField("ISO: "+loc1[i].getLanguage()+"==name: "+loc1[i].getDisplayLanguage(),Field.FOCUSABLE);
add(rh1);
}
String []loc2=Locale.getISOLanguages();
for(int i=0;i<loc2.length;i++)
{
System.out.println("=====2: "+loc2[i]);
RichTextField rh2=new RichTextField("ISO: "+loc2[i],Field.FOCUSABLE);
add(rh2);
}
in both cases it is displaying as attachment.
And strange thing is that in both array's i am not finding any language named as "Gujarathi" or "gu(ISO code)". But perfectly displaying data on my 9780 but 9800 not showing.
So Here i want to know what is the reason behind this ?
1) If suppose my devise is supporting "Gujarathi" Language then why it is not showing it's name in Locale.getISOLanguages(); or Locale.getAvailableInputLocales();?
2)How can we know that current device can support required language language?
I also tried using desktop-manager--->Applications------->available languages even here also i am not finding anything related to indian languages
I need to give answer to Client that what is the reason behind this ?
I goggled for 12Hrs. But no use So i decided that you are my only hope?
Try Checking Localization Demo
http://docs.blackberry.com/en/developers/deliverables/33805/Localization_sample_app_files_1791764_11.jsp

UIAutomation with Instruments - How to tap copy/paste buttons?

I'm using Instruments for iOS automation and I can't seem to figure out how to tap options on the copy/paste menu. When I do a logElementTree(),I see that we are returning a UIEditingMenu and then three elements (which correspond to options of that menu, such as copy/paste, etc..). I am attempting to place this into a variable, and then trying to "tap" that variable but I cannot get that to work. Here is a sample of my code:
var target = UIATarget.localTarget();
var app = target.frontMostApp();
var window = app.mainWindow();
//This generates the highlighted text
app.dragInsideWithOptions({startOffset:{x:0.45, y:0.6}, endOffset:{x:0.45, y:0.6}, duration:1.5});
var copy = app.editingMenu.elements.withName("copyButton");
copy.tap();
Instruments returns, "0) UIAElementNil". In addition to the above, I've also tried:
app.elements.withName("copyButton")
window.elements.withName("copyButton")
So, I can get the editingMenu to produce the available options, but I cannot figure out a way to tap or select one of those options. I'm not quite sure I know how to reference those options to begin with.
Does anyone have any ideas?
Thanks!
You should try app.editingMenu().elements()[index].tap() where index is the index of the option you want to tap from the array of elements returned. I got my one working this way.
Hey.
First of all, I was always using .elements() not .elements... but it is JS, so it may be invoking function that is assigned to object property..?
Anyway, maybe this edit menu is not internal window of the app, but it is system level menu, that is invoked, when you do the drag? If that is true, try:
UIATarget.localTarget().frontMostApp().elements().withName("copyButton").tap();
But as I see in apple reference your version with calling app.editingMenu() should be fine...
Maybe try calling buttons by position, and you will see which respond:
UIATarget.localTarget().frontMostApp().editingMenu().elements()[0].tap;
UIATarget.localTarget().frontMostApp().editingMenu().elements()[1].tap;
UIATarget.localTarget().frontMostApp().editingMenu().elements()[2].tap;
You should find position of correct one this way. When you have it's position you can check its properties by button.logElement();. With this inf you you should be able to switch back to .withName method instead hardcoded position.
I did this similar to yoosiba but with editingMenu element names.
Using Xcode 4.5.1 and device running iOS 6.
Using Alex Vollmer's excellent tuneup_js for target, app and vtap().
Otherwise you can use UIATarget.localTarget().frontMostApp() and tap().
NOTE: vtap() will delay and retry tapping. Without this you may need to add your own delays.
// tap in textFieldA to see editingMenu.
app.mainWindow().textFields()["textFieldA"].vtap();
app.editingMenu().elements()["Select All"].vtap();
app.editingMenu().elements()["Copy"].vtap();
// must delay before attempting next tap
target.delay(2);
// ... navigate to different section of the app
// tap in textFieldB to see editingMenu.
app.mainWindow().textFields()["textFieldB"].vtap();
// paste clipboard contents copied from textFieldA into textFieldB
app.editingMenu().elements()["Paste"].vtap();
target.delay(2);

Resources