I'm currently using the WebAii automation framework to write some user interface tests against a Silverlight 3 application. I'm new to Silverlight and suspect that I'm missing some bit of information about the HyperlinkButton.
The application has a HyperlinkButton and I'm attempting to write code that navigates to the page, finds the button the page, then "clicks" that button (which will then navigate to the NavigateUri as specified in the HyperlinkButton's properties).
I can't figure out how to execute that click. The code I have thus far (simplified):
Manager.LaunchNewBrowser(BrowserType.InternetExplorer);
ActiveBrowser.NavigateTo("http://server/appname/");
var slApp = ActiveBrowser.SilverlightApps()[0];
var menu = slApp.FindName<StackPanel>("LinksStackPanel");
var linkicareabout = menu.Find.ByName<HyperlinkButton>("Some Cases");
I'd expect to see some sort of Click() action, or Navigate() method that I could invoke on the "linkicareabout" variable, but I must be missing how it's done.
What you are looking for is the User object off the HyperlinkButton. All controls that WebAii comes with have that object. This way you can invoke any user action on any control type.
linkicareabout.User.Click()
The User object supports any user action you can think of and mimic real user interactions. Check out the documention here.
I was unable to do this myself and instead, had to write my own navigation code. For Firefox and IE, you can just use HtmlPage.Window.Navigate to navigate to the desired URL.
However, Safari and Chrome need some extra work. I had to use hidden HTML components and some javascript interops.
This workaround is detailed here.
Basically, it entails adding a hidden anchor and button to the HTML page containing your Silverlight control, and then modifying the anchor and clicking the button via calls to the DOM.
HtmlElement anchor = HtmlPage.Document.GetElementById("externalAnchor");
HtmlElement button = HtmlPage.Document.GetElementById("externalButton");
if ((anchor != null) && (button != null))
{
anchor.SetProperty("href", url);
button.Invoke("click", null);
}
Related
I am working on Protractor tests. Recently my web page changed where the terms and conditions are inside a textbox. Button Submit works only when the user scrolls through the textbox and clicks on Agree button. I tried the following option to scroll down but it is not scrolling down. Any help is greatly appreciated.
var scrollbar = element(by.id('terms-conditions'));
var checkbox = element(by.id('checkbox'));
scrollbar.click()
browser.executeScript('arguments[0].scrollIntoView()', scrollbar.getWebElement());
browser.executeScript('window.scrollTo(0,670);')
checkbox.click();
I followed the below link too but no luck.
Protractor: Scroll down
The second js execute statement you are using contains Window.scrollTo which references an open window in a browser. and using it only scrolls the complete window but not the pop-ups that appear inside a browser window
Refer here for documentation on Window.scrollTo
Normally terms and conditions shows up in a pop-up or may be a div and hence Window.scrollTo doesn't work
there are two ways you can do it
SOLUTION 1: use Jquery scrollTop() to scroll inside a specific webElement
Step 1: Identify the exact div that holds your terms of Service scroll bar
Step 2: Refine your js statement by trying directly in Chrome console
$('.modal-body').scrollTop() -> This returns the current position of scroll
$('.modal-body').scrollTop(10000) -> This sets the value of top position
Step 3: Incorporate this in your protractor script
browser.executeScript('$('.modal-body').scrollTop(10000)');
You can professionalize this by passing the element & scroll amount as arguments. Refer here
SOLUTION 2; The best way I see to submit a pop-up is not to deal with interface but to deal with the 'form' element behind it. Similar to how we deal with file uploads.No fuss & effective
May be try something like this, by making button visible first and then submit form
browser.executeScript is an asynchronous call, so you will need to put it into the controlFlow so that it will complete before clicking the checkbox:
scrollbar.click();
browser.controlFlow().execute(function() {
browser.executeScript('arguments[0].scrollIntoView()', scrollbar.getWebElement());
browser.executeScript('window.scrollTo(0,670);');
});
checkbox.click();
I have a main window with a custom Ext.panel.Panel using ExtJS 5.0.1.
Clicking an item shown on the custom panel creates and shows a custom Ext.window.Window for editing said item.
For the purpose of getting some kind of answer, or a starting point for my own situation, I'll ask for standard Ext components.
On closing the custom window, a variable in the custom panel needs to be updated to show that changes have been made.
This is a different requirement to a confirmation message before closing the window; the window does not control saving of information to a DB, but needs to let another component know that changes have been made.
This should be as simple as setting a boolean unsavedChanges to true on the panel if the window's information has been altered; I've performed this on a simpler page, which did not have the additional window as an obstacle.
Due to the use of the window, my typical go-to methods of calculating a variable as use of this.up or this.lookupReference returns null, or throw an error.
I'm aware that I can consider going to the parent of the page, then try and work down, but I'm not experienced enough to consolidate standard javaScript with the up and down capabilities of ExtJS, or at least understand the intricacies of ExtJS to navigate past the "item window" back to the panel.
How would I be able to refer to the panel while closing the window in order to update the panel's data?
Well, there's a couple of ways.
First, you can pass in your panel, or a callback function, during the construction of the window. e.g.:
// in panel
var window = Ext.create('MyWindow', { callingPanel: this })
...
// in window
onClose: function() { this.callingPanel.doStuff(); }
The other way to be to register a listener to the 'close' event of the window.
// in panel
var window = Ext.create('MyWindow', {
listeners: {
scope: this,
close: this.doStuff
}
})
The listener approach tends to work best when you don't want to tightly couple the window to the calling panel.
I have a form that has a WebBrowser control. Onload, it navigates to some URL.
On DocumentCompleted event handler, after getting the needed data the form is closed. This works most of the time, but sometime it pops up an IE window w/ the same URL after the form has already closed.
I noticed that in DebugView, it logs m_useSurfacePresenter 1. When this gets logged before the Close() is called, there is no popup. But when this gets logged after the Close() is called, then the popup appears.
You need to check the JavaScript .onunload event in that document, if it is set to open a new window (browser) when that page is unloading, then it will be triggered when you close your winform which is hosting the webbrowser control, and in turn, the page.
So, when you close the winform, the page's onUnload event in the webbrowser control will also be triggered as a result due to the way the events are chained in a Document/Page --> WB Control --> WinForms Form setup.
You can actually set this to nothing, by running a particular JS command directed to the page in the WB control, you can set the .OnUnload event to "function () {};", which will ensure whatever it is set to will be turned into Nothing/Null. Here is a code example:
window.onunload = function () { };
Let me know how it goes, and I will help you out if that doesn't fix it. Notice the above is JS, and there are ways to execute JS directly from teh WB Control, many examples on the web, there are actually 2 ways, one using .execScript and another one using the newer method, which is .InvokeScript.
I should create ExtJs4 app, which should have main menu, and each menu item should open a new page with different url, so if the user copies the url and pastes on other browser tab, the app should open that menu item.
I want to use ExtJs's recommended MVC architecture, but I don't know how I can use it with multiple pages/urls. All their examples are using single page.
One option is to reload the page each time when the user clicks on particular menu Item, so every url/menu item/page will be separate ExtJS app with it's MVC. But I think this approach has drawbacks, since the page will be reloaded every time and it's not good for performance. Also it's causes difficulties in reusing of components (common models, stores and views for different pages ).
So I would like to have one single app for all pages, but I don't know is there any solution to have different urls for different views (in my case: for different menu items).
Or is there another approach for such applications?
You would probably want to use a Viewport, and make the Center Region a Container.
The Center Region Container would usually have a Card or Tab layout.
When the user navigates to a new view (Component), you add that view to the Container, and make it active.
The big mistake is to change the URL first. You don't want to do that.
You want to navigate, and then set the URL if the navigation was successful. You should probably not use ExtJS's History component, as it is incorrectly implemented. I would recommend using HTML5 pushState.
You should make sure your navigation system works without changing the URL bar too.
I would recommend reading up on Navigation in Microsoft Prism, WPF, and Silverlight, as there is more documentation there, and then apply that to ExtJS.
http://msdn.microsoft.com/en-us/library/gg430881(v=pandp.40).aspx
Here is an example Navigation process:
call app.requestNavigate('contacts/5'); you would add this yourself.
you parse this fragment to:
navigationContext = {
fragment: 'contacts/5',
xtype: 'contacts-form',
parameters:{
id: 5
}
}
OPTIONAL: If using forms:
get active item from the navigation region (your center region). if exists, call confirmNavigationRequest(callback) . you will need to add this method or event.
if callback(true), proceed with the navigation. this allows the user to cancel a navigation, if say the form is "dirty"
END OPTIONAL
the easy way is to then create a new widget of navigationContext.xtype, add it to the navigation region, then call setActiveItem(widget). destroy the previous active item if it existed.
then call history.pushState(null, null, navigationContext.fragment)
then raise a 'navigatedto' event on the view, passing the context, and you can load the data from there.
More advanced scenarios include:
keep the previous component alive if you expect to return to it. add a keepAlive property and if true, don't destroy when add new components to container.
search the container and ask each component if it wants to handle the current navigation request (for example if a form loaded with contact-5 was already hidden in your navigation region, or if you want to re-use a form)
I am developing a website that contains a number of "forms" for entering data, etc, and I plan on using Silverlight and RIA Services for managing the data within these forms. The rest of the site will be normal HTML/CSS/JavaScript.
The plan was to create a single Silverlight control with many pages and each page would represent a single form. A HTML page would display this control, but would display a specific page within the Silverlight control.
So, my questions are:
When embedding a Silverlight control within a HTML page how would have the control automatically navigate to a specific page?
After loading a HTML page, and display the Silverlight control, would it be possible to have some JavaScript tell the Silverlight control to navigate to another page?
1 - Silverlight uses URL bookmarks on the end of the URL to emulate navigation.
e.g. http://somesite.com/somepage.aspx#formname
You can also override the default behaviour of the navigation so that it can do cool things like use the bookmark parameter to dynamically specify the name of the Silverlight form you want to show.
2 - You would only need to ensure the bookmark part of your site URLs contain something the Silverlight application can interpret.
Lookup the INavigationContentLoader interface for examples of overriding the navigation with custom behaviour.I found a few articles on the subject quite easily. Try this one.
After a bit of searching I found that the "object" tag that defines the Silverlight control in HTML can have a "initParams" element within it.
So, my thought is each page that I create will only ever have one "form" therefore in the "object" tag I just set "initParams" to define which page the Silverlight control should set as the "RootVisual".
When the control loads the Application_Startup will look at the "initParams" and use that to determine what page it needs to create and assign it to the RootVisual property of the application.
James
1) One of the solutions (not the best one) would be like this:
private void Application_Startup(object sender, StartupEventArgs e)
{
var page = HtmlPage.Document.QueryString["Page"];
RootVisual = GetPage(page);
}
private UIElement GetPage(string page)
{
switch (page)
{
case "page1": return new Page1();
case "page2": return new Page2();
default: return new PageNotFound();
}
}
2) If you want to interact Silverlight control with HTML (JavaScript), then
this is called a 'Silverlight HTML bridge':
HTML Bridge: Interaction Between HTML and Managed Code