I want to access device settings, I checked there are similar posts but no answer for real device.
I tried passing parameters as
desired_caps['app'] = 'settings' and desired_caps['bundleId'] = 'com.apple.Preferences'
But I get error Instruments Trace Error : Target failed to run: Permission to debug com.apple.Preferences was denied. The app must be signed with a development identity (e.g. iOS Developer).
Seems like above works on simulator but not device.
I can launch my test app, so I'm passing other parameters correctly.
Or is there any other way to access device settings?
desired_caps = dict()
desired_caps['platformName'] = 'iOS'
desired_caps['platformVersion'] = '9.2.1'
desired_caps['deviceName'] = 'iPhone'
desired_caps['udid'] = '09d905a'
desired_caps['app'] = 'settings'
# desired_caps['bundleId'] = 'com.apple.Preferences'
# desired_caps['fullReset'] = True
desired_caps['newCommandTimeout'] = 1000
config_iOS.driver_settings = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
For check all the info related to device you can use ios-deploy library. As per my knowledge you are Missing something. Can you attach appium logs.?
It's not possible to automate application which is on profile other than development. As the error says Settings application settings application of the application is build with development profile.
So the first moment when you try to fetch any element it will show the error.
In short, You can't automate application downloaded from app store/system application or installed with release mode using Appium.
Related
I have an app for iPhone and always sending a testing builds to client. At the same time I have an App Store version of this app. Client wants to have beta and stable app version on device at the same time. Is it possible to do without creating a new app with another bundle id?
You can only have on app on your device with the same BundleID.
If you want both the appstore version and a test version you will need to create a new BundleID for this test version.
I suspect you could do this using separate IDs for the debug and built app and using multiple schemes to share the code base between them.
Check out this article that will help
http://nilsou.com/blog/2013/07/29/how-to-have-two-versions-of-the-same-app-on-your-device/
--Edit--
Just noticed you specifically don't want different bundles due to Push Notifications. We got around this by letting our back end services know which app we were using, and targeting the different services based on which app they use. You can do this by defining preprocessor macros like this: Add preprocessor macro to a target in xcode 6
... then reference them just before you call your back end service to register your device like this...
#ifdef ENTERPRISE
env = GLOBAL_PushNotificationEnvironmentEnt;
#endif
#ifdef DEBUG
// In debug mode, the environment should be set to Development
env = GLOBAL_PushNotificationEnvironmentDev;
#endif
if (notificationsOnBool) {
[service RegisterPushNotificationTarget:self
TargetType:GLOBAL_PushNotificationTargetType
TargetToken:deviceID
DeviceName:[UIDevice currentDevice].name
EnvironmentType:env];
}
... then in your back end code you do something like this (psuedo-code)
if (device.env == Fabric) {
sendNotification(fabricService);
} else {
sendNotification(prodService);
}
I am writing an automation script using Java + TestNG + Appium.
In a test scenario, I am trying to launch already installed application on iphone. (Box in this case). Box contains some MS office file which I need to access.
I am not very sure how can I achieve this.
I tried multiple options such as extracting .app file from iTunes and deploying using Appium, but no success.
Can someone please guide me, if this is possible. If yes, how?
Automate a preinstalled app with following scenario.
1.This will only work for applications that are signed with a DEVELOPMENT cert.
2.This will NOT work for applications that are signed with a DISTRIBUTION cert
3.If you have created the app with a developer provisioning profile, and built yourself. Or downloaded it using testFlight, and is signed with a development provisioning profile
4.This is because Apple's Instruments will not allow you to interact with those applications which is live. (Even if you knew the bundleId)
if your app is in development mode please follow these things
1.The bundleId of the app that was installed on the device. Use that as the app capability.
Follow the Appium Real Devices guide (substitute any .ipa/.app reference with the bundleId)
In addition to your regular desiredCapabilities (ex. platformName, platformVersion, deviceName).. these should be your desiredCapabilities:
For preinstalled apps
desiredCaps['app'] = 'yourbindleID'
Device's unique identifier
desiredCaps['udid'] = '1824y983h2849gh2498'
this works for me
HashmMap<String, Object> args = new HashMap<String,Object>();
args.put("bundleId","*YOUR_APP_BUNDLEID*");
driver.executeScript("mobile: launchApp", args);
Refer below code snippet:
cap.setCapability(IOSMobileCapabilityType.APP_NAME, "{appName}");
This capability is the MOST important capability to open the app automatically if the app is already installed on mobile device.
public static IOSDriver<IOSElement> capabilities() throws IOException {
//Configure absolute path of the .ipa file
FileInputStream fis = new FileInputStream(System.getProperty("user.dir")+"//automation.properties");
System.out.println(fis);
Properties prop = new Properties();
prop.load(fis);
File f = new File("src/test/resources");
File fs = new File(f, (String)prop.get("iOSAppName"));
DesiredCapabilities cap = new DesiredCapabilities();
cap.setCapability(MobileCapabilityType.PLATFORM_NAME, (String)prop.get("iOSPlatformName"));
cap.setCapability(MobileCapabilityType.UDID, (String)prop.get("iDeviceUDID"));
cap.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST);
cap.setCapability(MobileCapabilityType.DEVICE_NAME, "iPhone");
driveriOS = new IOSDriver<IOSElement>(new URL("http://127.0.0.1:4725/wd/hub"), cap);
//Check app is already installed if NOT install app to device automatically
if(driveriOS.isAppInstalled("com.test.app")==false)
{
cap.setCapability(MobileCapabilityType.APP, fs.getAbsolutePath());
}
//cap.setCapability(MobileCapabilityType.BROWSER_NAME, (String)prop.get("iOSBrowserType"));
cap.setCapability(MobileCapabilityType.PLATFORM_VERSION, (String)prop.get("iOSPlatformVersion"));
cap.setCapability(IOSMobileCapabilityType.APP_NAME, "{appName}"); //Provide your app name here
cap.setCapability(IOSMobileCapabilityType.BUNDLE_ID, (String)prop.get("updateWDABundleId"));
cap.setCapability("xcodeSigningId", "iPhone Developer");
cap.setCapability("xcodeOrgId", (String)prop.get("xcodeOrgId"));
driveriOS = new IOSDriver<IOSElement>(new URL("http://127.0.0.1:4725/wd/hub"), cap);
driveriOS.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
stepRecorder(Status.INFO, "iOS Driver initiated");
return driveriOS;
}
I've iOS app that needs some privileges (GPS, Push notifications).
When app starts for a first time iOS asks user if they're ok with granting those permissions to application.
I've written some UITests and want to automate running them on locally connected iPhone.
The problem is that I cannot override permissions questions and my tests fails.
I found out that application deployed by IDE (Xamarin Studio) will ask for permissions, but application deployed via UITests will not.
So I tried with .AppBundle(path_to_app) but it says this is only valid for deploying to Simulator.
SetUp : System.Exception : This app bundle is not valid for running on
a simulator. To fix this issue please ensure that your target device
is a simulator. DTPlatformName is 'iphoneos', not 'iphonesimulator' in
the apps Info.plist.
Like it's trying to deploy iPhone app to Simulator. But Target in Xamarin Studio is set to real device.
I tried to add .DeviceIdentifier. When Used with .InstalledApp it was starting up (still asking for permissions).
But when I used DeviceIdentifier and AppBundle there was the same error as above.
My tests works fine on Test Cloud. They work fine on Simulator.
They work fine when I deploy to device manually, start app and approve permissions then run UI tests.
What I cannot achieve is to make UITests override permissions questions on real device.
Anyone made this work?
Last thing is that I found is in documentation for AppBundle method
"Will force a run on simulator"
https://developer.xamarin.com/api/member/Xamarin.UITest.Configuration.iOSAppConfigurator.AppBundle/p/System.String/
So I may be doomed with the task but maybe someone knows a workaround?
You can dismiss system dialogs with UITest by using InvokeUIA. The test below works by tapping the "OK" button of an iOS system alert:
[Test]
public void AppLaunches ()
{
app.Screenshot ("First screen.");
app.InvokeUia ("uia.query('[:view {:marked \"OK\"}]')");
app.InvokeUia ("uia.tapMark(\"OK\")");
}
A working sample app & UITest is also here:
https://github.com/King-of-Spades/InvokeUia-for-System-Dialogs
Warning about system dialogs in Test Cloud
The reason that you don't see this issue in Test Cloud is because Test Cloud automatically dismisses the system alerts; so usually you don't have to worry about it. However, if your alert launches too soon; so that it appears before the automation has fully started your app, then it will be unable to detect & dismiss the alert and cause your test to fail.
So you want to make sure that when running your app in Test Cloud that the request for permissions are delayed, or you can even deactivate them if they aren't explicitly needed for a particular test. More information is available in this Calabash guide: https://github.com/calabash/calabash-ios/wiki/Managing-Privacy-Alerts%3A--Location-Services%2C-APNS%2C-Contacts
(Even though it's Calabash, you can use the same strategy in UITest; albeit with a C# syntax.)
Update for Xcode 8 / iOS 10
Xcode 8 / iOS 10 removed UIAutomation, so the InvokeUIA workaround will only continue to be possible if you're using Xcode 7 and iOS 7-9. References:
UITest: https://developer.xamarin.com/guides/testcloud/UITest/xcode7/
Calabash: https://developer.xamarin.com/guides/testcloud/calabash/xcode7/#Automation_API
For real devices you dont need any of those.
{
app = ConfigureApp
.iOSAppBundle
.StartApp();
}
this piece of code is good enough, if you are connecting real device to the system, then select that before running.
We use this to execute the UI tests on iPhones:
ConfigureApp.iOS.InstalledApp("com.appcenter.UITestDemo").StartApp();
InstalledApp requires you to build an IPA using the Debug
configuration & a valid provisioning profile, and preinstalling it on
the target device.
https://github.com/microsoft/appcenter-Xamarin.UITest-Demo/blob/main/UITestDemo.UITest/AppInitializer.cs
To confirm system dialogs we use this:
private Query ConfirmLocalNetworkPermissionDialogButton
=> AppInitializer.Platform == Platform.iOS
? new Query(x => x.ClassFull("_UIAlertControllerActionView").Marked("OK"))
: x => x.Class("AppCompatButton").Marked("button1");
I am performing following steps
Set capabilities and launch ABC app. By providing app path
capabilities.setCapability("app", "/Users/changdeojadhav/Library/Developer/Xcode/DerivedData/ABC/Build/Products/Debug-iphonesimulator/ABC.app");
capabilities.setCapability("bundleId","com.abc.ABC-Demo");
Perform some actions
quit driver by driver.quit()
Set capabilities for Xyz app. And launch XYZ app
Perform some steps
quit driver by driver.quit()
relaunch ABC app as mentioned in step #1.
Expected is "App ABC should retain it's state" but ABC gets reset.
I have launched appium with --no-reset parameter.
Any idea about what I am missing here
Thanks
As far as I can tell, there is currently no solution to reopening the application after going to the home screen without clearing the app from cache.
In past versions of iOS/Appium, the solution was to do:
from appium import webdriver
driver = webdriver.Remote('http://0.0.0.0:4723/wd/hub', desired_caps)
driver.close_app()
app = driver.find_element_by_xpath('//UIAApplication/UIAWindow/UIAScrollView/UIAButton[#name="sampleApp"]')
app.click()
However this currently crashes Appium
I will update this question when I log a github issue for it.
The Appium help page says that it only supports multiple app testing in a single test session for Android without Selendroid:
iOS: Support for automating multiple apps in one session: No
Android:Support for automating multiple apps in one session: Yes (but not when using the Selendroid backend)
http://appium.io/slate/en/master/?ruby#toc_27
I'm guessing that is why you are having this issue, and it's most likely an Instruments/XCode issue.
I was able to relaunch the same app without it resetting its state with Appium 1.3.1 running with Xcode 6.1 on a Mac Mini running Mavericks. I did not try launching another app in between launches. I'm driving the automation from C#.
protected AppiumDriver GetAppiumDriver(bool forRestart = false)
{
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.SetCapability("appium-version", "1.0");
capabilities.SetCapability("platformName", "iOS");
capabilities.SetCapability("platformVersion", "7.1");
capabilities.SetCapability("deviceName", "iPhone Simulator");
capabilities.SetCapability("app", _appPath);
capabilities.SetCapability("locationServicesEnabled", true);
if (forRestart)
{
capabilities.SetCapability("noReset", true);
}
AppiumDriver driver = new AppiumDriver(_serverUrl), capabilities, new TimeSpan(0, 5, 0));
return driver;
}
public void iOSMobileAppBasicUITest()
{
// Initially Launch the app with the noReset capability at its default value of false to ensure a clean starting point.
_driver = GetAppiumDriver(false);
//Shut down the app.
_driver.Quit();
// Launch the app again, this time with the noReset capability set to true.
_driver = GetAppiumDriver(true);
// Use _driver to do whatever UI automation is desired.
// Optional: Send the app to the background so that iOS does state preservation.
_driver.BackgroundApp(3);
// Close the app.
_driver.CloseApp();
// Alternative: _driver.Quit();
// Launch the app.
_driver.LaunchApp();
// Alternative: _driver = GetAppiumDriver(true);
...
As I known, Appium by default runs in fast reset mode, and it tries to clear app's data when the session ends (as a result of the invocation of quit() in this case). If your want to keep app's data, the option --no-reset should work for you.
We have a iOS and Android Hybrid App Environment in which we have App Authenticity successfully running (drop down available to control the feature) using:
<mobileSecurityTest name="app">
<testAppAuthenticity/>
<testUser realm="wl_anonymousUserRealm"/>
<testDeviceId provisioningType="none" />
</mobileSecurityTest>
We added a "iOS Native API" project to our Worklight project that we use for our native iOS client development in XCode 5. We are successfully able to connect to the WL server and call all our existing adapter procedures in our different adapters.
For this native API project, we now would like to enable App Authenticity as well. When we use the same MobileSecurityTest as in the hybrid app in the application descriptor of the native API project we can deploy it to our WL server and the App Authenticity feature is enabled (drop down available to control the feature) at the iOS Native API entry in the console.
On the native iOS app/project we set:
bundle ID is exactly the same as in the hybrid project and the same as in the Apple Developer portal
Key Chain is enabled in the project and also set to worklight.group (as in the hybrid XCode project)
we are not able to get a successful authentication running when we want to connect to WL server. We see that the DeviceAuthManager tries to get the UUID from the device, but then the server returns an error response:
2013-09-24 08:58:35.530 App[32535:c07] DeviceAuthManager:getWorklightUniqueDeviceId --> returning UUID from the keychain
2013-09-24 08:58:35.564 App[32535:c07]
isCustomResponse
2013-09-24 08:58:35.564 App[32535:c07] this is it: Status: 403
InvocationResult: (null)
InvocationContext: {
delegate = "<MyConnectionListener: 0x7d73ec0>";
}
Response text: /*-secure-
{"WL-Authentication-Failure":{"wl_authenticityRealm":{"reason":"com.ibm.json.java.JSONObject cannot be cast to java.lang.String"}}}*/
2013-09-24 08:58:35.564 App[32535:c07] [ERROR] Worklight: -[WLRequest requestFailed:]:309::Status code='403' error='(null)'
2013-09-24 08:58:35.565 App[32535:c07] [ERROR] Worklight: -[WLClient onInitRequestFailure:userInfo:]:410::
We did try this with and without a registered ChallengeHandler that just prints the response. The same results, just that we can see the error response printed in the isCustomResponse method if we have the ChallengeHandler.
Also, a Worklight dialog is shown automatically that says "Error: An error was encountered while processing the request from the application (CLOSE)".
We can see that in 6.0 there is the worklight.plist value:
<key>wlUid</key>
<string>wY/mbnwKTDDYQUvuQCdSgg==</string>
is that also necessary in 5.0.6? Our plist file there does not have that.
When we change the environment value in the worklight.plist file from iOSnative to our app name (or something else) we get a response Response text:
{"errorCode":"UNEXPECTED_ERROR","errorMsg":null}
so I assume this value iOSnative is a fixed value that has to be there?
Sept 30th: WL 6.0.0.1 Update
In WL 6.0.0.1 it seems to not show the same bug when we used it with a Studio 6.0.0 generated iOSApi Environment deployed to a Consumer Server on Tomcat.
Now we are getting an:
Invocation Failure: Status: 403
InvocationResult: {
"WL-Authentication-Failure" = {
"wl_authenticityRealm" = {
reason = "forbidden state";
};
};
}
when we have Enabled, blocking and we can connect and call Adapters when we change to Enabled, servicing. (which was not possible with the 5.0.6 bug before)
Now we assume we need to somehow setup our iOS Certificates or Signatures that we use to sign the app for the iOS Simulator and for the iOS Devices (Developer and Distribution Certificates) on the Wl server, so that the WL Server allows a connection?
Could someone help us with the steps that we need to take to setup an iOS native App Authenticity in our XCode 5 project to successfully connect to the server and after that call our adapters with Enabled, blocking.
We did add worklight.group to the turned-on Keychain Sharing capability of the iOS app.
We copied all Wl iOSAPI files including the plist file with the wlUid into the iOS app xCode5 project?
As mentioned above, it works with Enabled-Servicing and with Disabled AppAuthenticity fine.
For App Authenticity to function in a native iOS application using the Worklight Native API for iOS, the steps are the same as in a Hybrid application on the Eclipse side:
Setup the securityTest in authenticationConfig.xml
Add the securityTest to the iPhone environment application-descriptor.xml
Add your bundleId to the iPhone environment in application-descriptor.xml
There is, however, 1 extra step to do - in Xcode.
Once you open the generated Xcode project:
Under Build Settings > Linking > Other Linker Flags
Add the flag -ObjC
Now you can Clean and/or Run the project on the iOS Simulator/device. Should work.