What is the bundle Id of the process that displays security alerts in iOS 11.3? - xcuitest

I'd like to be able to address this from a XCUITest in order to say something like
XCUIApplication(bundleIdentifier: "bundle Id").alerts.matching(Foo)
I already know about addUIInterruptionMonitor(withDescription: description),
but it seems that we might need to wait for the alert to appear.

It is Springboard app, therefore its Bundle ID is com.apple.springboard.
You have it in your logs when you run your tests. This is excerpt from my test logs:
t = 31.89s Tap "Location service" Switch
t = 31.89s Wait for com.mytestapp to idle
t = 31.95s Find the "Location service" Switch
t = 32.01s Wait for com.apple.springboard to idle
t = 32.05s Synthesize event
t = 32.16s Wait for com.mytestapp to idle

Related

Wait for App to idle after Interruption

I have a ViewController that will request access to location services on init via
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined)
{
[_locationManager requestWhenInUseAuthorization];
}
This triggers the "Allow app to access your location while you use the app?"-alert.
I use [self addUIInterruptionMonitorWithDescription:handler:] to react to this. I am encountering the following problem: after dismissing the request-dialog, the ui-test does not continue. The alert is dismissed, but Xcode waits for the app to become idle, but it looks like the app is idle:
t = 67.35s Wait for app to idle
The test fails, because the app is stuck here. If i tap into the simulator, Xcode logs.
t = 72.27s Synthesize event
and continues the test.
Is there a reason, why Xcode tries to wait for the app? A workaround seems to be to tell Xcode that the UI changed or an event happened. Is there a way to trigger this?
After presenting the alert you must interact with the interface. This is a known bug with Xcode 7.2. Simply tapping the app works just fine, but is required.
addUIInterruptionMonitorWithDescription("Location Dialog") { (alert) -> Bool in
alert.buttons["Allow"].tap()
return true
}
app.buttons["Find Games Nearby?"].tap()
app.tap() // need to interact with the app for the handler to fire
XCTAssert(app.staticTexts["Authorized"].exists)
See my blog post for more information.

XCode 7 UI Testing: Dismissal of system-generated UIAlertController does not work

I have a UI test which involves the dismissal of a system-generated UIAlertController. This alert asks the user for the permission to access the device's calendar. The objective of the test is the behaviour after a tap on the OK button:
1 let app = XCUIApplication()
...
// this code was basically generated by the recording feature of XCode 7
2 app.alerts.elementBoundByIndex(0).collectionViews.buttons["OK"].tap()
Now, instead of clicking the OK button, line 2 makes the simulator tap onto the first button which happens to be the Cancel button...
Additionally, I found out that the testing framework does not accurately recognize the appearing alert. So if I check the current count of alerts I always get 0:
// ...tap...
let count = app.alerts.count // == 0
This also happens if I use an NSPredicate for the condition and wait for several seconds.
Is it possible that UI tests do not work reliably with system-generated alerts? I am using XCode 7.0.1.
Xcode 7.1 has finally fixed the issue with system alerts. There are, however, two small gotchas.
First, you need to set up a "UI Interuption Handler" before presenting the alert. This is our way of telling the framework how to handle an alert when it appears.
Second, after presenting the alert you must interact with the interface. Simply tapping the app works just fine, but is required.
addUIInterruptionMonitorWithDescription("Location Dialog") { (alert) -> Bool in
alert.buttons["Allow"].tap()
return true
}
app.buttons["Request Location"].tap()
app.tap() // need to interact with the app for the handler to fire
The "Location Dialog" is just a string to help the developer identify which handler was accessed, it is not specific to the type of alert. I believe that returning true from the handler marks it as "complete", which means it won't be called again.
I managed to dismiss access prompt for contacts like this:
let alert = app.alerts["\u{201c}******\u{201d} Would Like to Access Your Contacts"].collectionViews.buttons["OK"]
if alert.exists
{
alert.tap()
}
Replace asterisks with your app's name. It might work the same for calendar.
This is what I ended up using to get the prompt to appear and then allow access to Contacts:
func allowAccessToContacts(textFieldsName: String)
{
let app = XCUIApplication()
let textField = app.textFields[textFieldsName]
textField.tap()
textField.typeText("aaa")
let alert = app.alerts["\u{201c}******\u{201d} Would Like to Access Your Contacts"].collectionViews.buttons["OK"]
if alert.exists
{
alert.tap()
}
textField.typeText("\u{8}\u{8}\u{8}")
}

Use the chrome.idle API to restart application

I have a Chrome kiosk app that basically just uses webview to allow someone to browse through a catalog.
I found the chrome.idle API, and believe I understand how to set idle time and query if the device is idle, but can I have it restart the application when the state changes to idle or at least navigate back to a set URL?
The end goal is to have the catalog reset itself for the next user after being left idle for a set period of time.
https://developer.chrome.com/apps/idle
Well, the documentation is pretty clear..
First, you need to declare in the manifest that you want to use this API, as it needs a permission.
"permissions" : ["idle"],
You could go with a poll-based approach as you suggested, but why? There's an event provided. So, we go on to use that.
You need to inform Chrome how long an interval without user input you consider an idle state.
chrome.idle.setDetectionInterval(120); // 120 seconds
Lastly, you need to react to a change to an idle state.
chrome.idle.onStateChanged.addListener(function(newState) {
if(newState == "idle") {
// Reset the state as you wish
}
});

Speech Recognition in Call : Windows Phone 8

I have a below requirement in Windows Phone 8 to run voice listener in background agent whenever an incoming call comes or for an outgoing call. The voice listener should stop when there was NO call.
Eg: When I lift an incoming call and while speaking. I would like to say a voice command say "SPEAKER", then the speaker should ON
I saw obscured events can be used for detecting calls. But am unable to start the voice listener from background agent. Kindly please assist.
Here is the method I am using in the ScheduledAgent.cs file, but no luck
private async void SpeakTest()
{
SpeechRecognizerUI speechRecognition = new SpeechRecognizerUI();
SpeechRecognitionUIResult recoResult = await speechRecognition.RecognizeWithUIAsync();
if (recoResult.ResultStatus == SpeechRecognitionUIStatus.Succeeded)
{
lblMessage.Text = recoResult.RecognitionResult.Text;
}
}
First, You can not run a background task whenever you want. OS will decide when to run your task agent. It'll not run continuously. Rather it'll run in interval
Second, In windows phone 8 ( not elsewhere) the microphone is muted to external app.
Third, You shouldn't try to run SpeechRecognizerUI from background agent.

offline_message_hook: does not get called when one sends an offline message

I am developing, chat application for android using ejabberd as XMPP server. I want to send GCM push notification, when user is offline. For that I am creating new module in ejabberd, registerd offline_message_hook, but this function gets called only when somebody starts typing and finishes typing. Below are the only packets passed to this hook. Although, user receive message when he/she comes online.
Packet: {xmlelement,
"message",
[{"type",
"chat"},
{"id",
"purple7d4d0773"},
{"to",
"xxx#rakshith"}],
[{xmlelement,
"paused",
[{"xmlns",
"http://jabber.org/protocol/chatstates"}],
[]}]}
Packet: {xmlelement,
"message",
[{"type",
"chat"},
{"id",
"purple7d4d0773"},
{"to",
"xxx#rakshith"}],
[{xmlelement,
"composing",
[{"xmlns",
"http://jabber.org/protocol/chatstates"}],
[]}]}
Two things about hooks in ejabberd:
1) The callbacks are called always in order, the order is defined by the priority you specify when registering it.
2) If a callback return 'stop' it prevents the event to be propagated to the rest of the listeners on the chain.
What is happening is that the ejabberd offline module is listening in the offline_message_hook, the same than your code. It handles the message, and returns 'stop', so your code isn't executed.
(your code do receive the message for the chatstates notifications because those are ignored by the offline module, and so it don't stop the chain in those cases).
You probably wants your code to be run before the offline storage module. Just remember to not return 'stop' so the offline module has the oportunity to store the message.