In UI/Automation Testing using Xcode 7, is there a way to list all of the XCUIElements on an app screen? Like in a tree or list, or even something in the Xcode UI? I can record tests for the app under test using clicks, but when I go to run the test, it fails. It fails because it can't find the XCUIElements from the generated code.
You can view it in Xcode hierarchy debugger.
From Apple Docs:
To enter the view debugger, run your app in Xcode and click the Debug View Hierarchy button in the debug bar.
You can debug the state of UI element using,
XCUIElement.debugDescription
It returns a snapshot of UIView in html format with a nice look up into the UI elements state with properties like element type(e.g textField, button), traits like focussed, enabled and values e.g placeholderValue.
You can also use accessibilityInspector app to look into accessibility attributes for the UI Elements on the view and verify that elements have accessibility properties set correctly.
Another handy tool to investigate the view is new hierarchy viewer which can be invoked during recording from debug console toolbar or Debug Navigator filter when you enable breakpoint in your test code.
Xcode 7 also has a nice test reporting under Report Navigator which can help you drill down exact reason with the test failure. e.g
UI Test Activity:
Assertion Failure: Asynchronous wait failed: Exceeded timeout of 10 seconds, with unfulfilled expectations: "Expect predicate `exists == 1` for object "Logout" Button".
Hope this helps.
Related
While loading a product into the Forge viewer using latest version of Chrome, user receives a message that states "WebGL context lost". They had a model loaded into the viewer which was working fine, clicked on another model to view it and that is when they received the error message (see attachment).
Is there anything that can be done to mitigate or resolve this issue?
Click for Picture of Error Message
Here are two possibilities for this issue:
The graphic card driver is out-date, please try to upgrade it: https://knowledge.autodesk.com/support/bim-360/troubleshooting/caas/sfdcarticles/sfdcarticles/Error-WebGL-context-lost-when-viewing-files-in-BIM-360.html
There might be some viewer instances that haven't been destroyed properly. you can type NOP_VIEWERS in your browser console to see if the array length is greater than two. To fix this, you can take advantage of viewer.finish() before loading other models.
After login in Chrome browser, I am getting a save password popup from the browser. I want to handle that popup and want to close that using Robot Framework
Browse popup window
Thanks
This question has been asked and answered before with a pure Python context. This answer continues on this SO post for a working Robot Example.
The popup you see is generated by Chrome itself. It's not an HTML alert. For this reason none of the Selenium2Library keywords will have any effect on it. Nor wil settings cookies or javascript.
These settings can be manually set using the chrome://settings link. Go to advanced settings and then scroll down to Passwords and Forms. Untick the second item and this will prevent the popup.
To do the same automatically in Robot Framework the WebDriver needs to be started with additional preferences:
Chrome With Preferences
${chrome_options} = Evaluate sys.modules['selenium.webdriver'].ChromeOptions() sys, selenium.webdriver
${prefs} Create Dictionary credentials_enable_service=${false}
Call Method ${chrome_options} add_experimental_option prefs ${prefs}
Call Method ${chrome_options} add_argument --disable-infobars
Create WebDriver Chrome chrome_options=${chrome_options}
Go To https://secure.url.com
This key things here are credentials_enable_service=${false} where it is important to use ${false} and not false, as the latter is interpreted as a string and then added to Chrome as "false" instead of the correct value false.
The second item is that preferences are not added as arguments but through assigning a dictionary to the prefs property of the ChromeOptions() object like so: add_experimental_option prefs ${prefs}
I do not think this is real to be honest (as it's property of the browser.) Are you having issues with that? The only thing you can dismiss is javascript alert and probably the best way to handle this is:
${alert} = Get Alert Message dismiss=${dismiss}
I have this in my test teardown with Run Keyword and Ignore Error, it makes me able to fetch optional js alert content and debug (also dismisses it do the rest of the suite can be executed.)
Three Ways To do do it.
1) Many a times, Once pop-up appear on screen and Disappear a cookie is set which you can view in developer console-> application. If you set this cookie with value using Add Cookie keyword. Pop- up wont appear.
2) if first doesn't work, then open developer tools and monitor the local store from developer tools -> application and close the pop-up. U will notice some variable with a value is stored in local storage. You can set that value using your script and u wont see the pop-up while executing variable.
3) If first and second doesn't work, the pop-up is most likely linked to a javascript variable. set java script variable using Execute Javascript Keyword and your problem must be solved.
Talk with your dev team, to see which way will work for you.
So I'm seeing some bizarre behavior in an appwidget that I wrote.
The widget itself is quite simple - it reads a few values from persistent storage and then displays them as text. Nothing fancy in the layout - just a FrameLayout root element with some Linear Layout and TextView children.
The widget has a simple configuration activity associated with it.
The bizarre behavior is that the widget will initially show "Problem Loading Widget" after the user closes the configuration activity, and then after a few seconds it shows a "Google Sound Search" button (and clicking on the button actually does launch Google Sound Search). Then, after a few more seconds, it finally shows the expected display.
I am away from my code right now, so I'll have to wait until tonight to post code snippets. However, in the meantime, can anyone provide some insight into how such a thing could happen? Has anyone else ever experienced this? How could another widget "hijack" mine?
Thanks,
-Ron
Here are some screenshots:
There are a couple of issues with your widget and there are answers to all of them (although you didn't post any code so some of my statements are based on assumptions):
"Problem loading widget": this is the default view Android uses before the widget is initialized and the layout updated. Simply add the following line to your widget xml configuration (to show a loading message instead of the problem message):
android:initialLayout="#layout/my_cool_widget_loading_message"
If the widget shows the wrong layout then you probably have an issue in the widget's onReceive method. onReceive is called for all the widgets no matter whether the broadcast is for that specific widget. Android's AppWidgetProvider filters the broadcasts by appwidget Id and dispatches to the other methods (like onUpdate).
See also: https://developer.android.com/reference/android/appwidget/AppWidgetProvider.html#onReceive(android.content.Context, android.content.Intent).
If you override onReceive (which I assume you do), you need to call through to super.onReceive(Context, Intent) to make sure your other methods don't get calls meant for other widgets.
Now for the configuration of the widget. If you follow the Google documentation then it will all work nicely. The only improvement I'd do is what my other answer that you reference suggests (https://stackoverflow.com/a/14991479/534471). This will NOT send out two broadcasts. The setResult()/finish() part does only terminate the config Activity and let Android know whether to actually add the widget or not (depending on whether the result is RESULT_CANCELED or RESULT_OK.
From your own answer I can see why your code wouldn't work. The code is:
Intent intent = new Intent();
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {mAppWidgetId});
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, intent);
sendBroadcast(intent);
finish();
First of all there's no need to add the appWidgetId twice, use the AppWidgetManager.EXTRA_APPWIDGET_IDS version and you're good. Second you're using the same Intent to return as a result for the Activity. AFAIK it's not documented what happens when you do set an action on that Intent but my experience with Android widgets is that you need to stick exactly to the documentation or you'll end up having strange issues (like the ones you encounter). So please use two different Intents.
Activity result:
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();
Broadcast:
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null, this, MyWidget.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {mAppWidgetId});
sendBroadcast(intent);
ok, so I figured it out. Posting here in case anyone else runs into this. I think that the Android Developer docs are a little misleading here.
The problem was that in my configuration Activity, I had this code at the end:
Intent intent = new Intent();
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {mAppWidgetId});
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, intent);
sendBroadcast(intent);
finish();
Providing an intent with the extra EXTRA_APPWIDGET_ID is recommended by the documentation provided by google.
However, that same document says that you have to update the widget's view by creating a RemoteView and calling AppWidgetManager.updateAppWidget() like so:
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.example_appwidget);
appWidgetManager.updateAppWidget(mAppWidgetId, views);
I didn't like the idea of placing the presentation logic in both the configuration activity and the widget class, so I instead decided to broadcast an intent at the end of the configuration activity to tell the widget to redraw itself. That's why I have setResult() AND sendBroadcast() at the end of the activity. The documentation further states that the onUpdate() callback will not be called when using a configuration activity. So this seemed neccessary. I added the ACTION_APPWIDGET_UPDATE and the EXTRA_APPWIDGET_IDS to the intent so that it would trigger the onUpdate() method. This practice was recommended by this SO answer (albeit without being included in the activity result intent - but I tried separating the two and it had no effect).
Now I'm not certain exactly how the "Google Sound Search" widget got in there, nor do I fully understand the mechanics of how the intents interacted to produce the observed results. However, as soon as I replaced my code above with the code stated in the docs, the widget was updated properly.
Intent resultIntent = new Intent();
resultIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultIntent);
finish();
This seems to contradict the documentation's statement that the configuration activity must update the widget's view. Simply providing the configuration activity result as below triggers the onUpdate() method in the widget, thus allowing the widget to redraw itself. I confirmed the behavior on an emulator running API 23 and also on a Samsung device running Samsung's android flavor.
I am writing a gtkmm3 application and I need to create and show new GUI elements from a non-GUI thread. Specifically, I am trying to add a tab to a notebook.
I create the notebook in the gui thread like so:
Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");
if(!Glib::thread_supported()) Glib::thread_init();
Gtk::Window window;
notebook = new Gtk::Notebook();
window.add(*notebook);
notebook -> show();
Worker bee;
bee.start();
return app->run(window);
and the I create and add a new tab like so:
Gtk::Label label("label");
Gtk::Label child("child");
notebook -> append_page(child, label);
notebook -> show_all();
If I insert the tab creation code before notebook->show() it works fine. But if I put the tab creation code into its own worker thread, the new tab never shows.
I'm guessing that the failure has to do with the fact that the new tab is created on the worker thread and that violates gtkmm's GUI stuff on the GUI thread convention.
The trouble is that the worker thread is responsible for creating new tabs, and I don't know how many tabs to create at compile time.
In APIs like Swing, and gtk+ there are mechanisms to handle this case. In Swing there is an invokeLater method that allows me to pass a lambda to the GUI thread for invokation, and gtk+ uses gdk_threads_enter/leave to ensure that only one thread is playing the GUI at once.
What is gtkmm's answer to this issue?
In general you should just avoid ever using GTK+ (or gtkmm) UI API from anything but the main thread. It's not meant to work.
You need to let the main thread respond when the other thread says that it should, instead of actually doing the UI work in the other thread. People like to use Glib::Dispatcher for this with gtkmm: https://developer.gnome.org/gtkmm-tutorial/stable/sec-using-glib-dispatcher.html.en .
But also think hard about whether you really need another thread at all. It might be fine to do the work in an idle handler: https://developer.gnome.org/gtkmm-tutorial/stable/sec-idle-functions.html.en
If i execute NPN_Evaluate in plugin, when camera preview is running, the whole ui gets blocked and does not take any input from the user. My understanding was am doing NPN_Evaluate on a wrong NPObject which i get using NPN_GetValue( Npp, NPNVWindowNPObject, &sWindowObj). The script am trying to evaluate is like this:
"confirm (\'Do you want to Capture Image\');"
which shows a popup above camera preview asking to capture image.
ok guys... I found the problem. I was trying to evaluate the javascript from a native call from java to jni. when i changed the thread of execution, the problem was solved.