Simulating clicks, keyboard input etc in a web view? - vb.net

I have decided to have some fun with VB.NET and make a bot for some online games.
First of all, I plan on viewing the game through a webview control, which I believe is perfectly possible... unless I can't see Flash/Java content?
If it is possible, I've been wondering how would you "simulate a click" in the web view control? And, of course, keyboard input?

Perhaps a little late and I have no experience with VB.NET but to work with keys on a web page you need to use Javascript. For example:
<html>
<head>
<script>
document.onkeyup = function(event){ console.log(event); };
</script>
</head>
<body>
press a key within this document.
</body>
</html>
Cursor keys don't generate a keypress event hence the use of onkeyup. Also note it's lowercase. onKeyUp is not correct. If you're using Chrome or Firefox console.log will output the object that you can inspect. Not sure about IE but I think later versions support this too. Properties and methods can be used to get the keycode, character and any modifiers.
This code was tested on Chrome 12 beta. There are differences between IE and other browsers (as usual). This page shows an example of some of the differences: http://www.w3schools.com/jsref/event_onkeypress.asp
Not sure what you mean by "simulate a click" but I suspect you're not referring to testing.

Try for WatiN, its like testing a web application

Related

NightwatchJS: Safari can't find nested iFrame

I'm having difficulty testing a piece of code using NightwatchJS with Selenium and SafariDriver.
I have an open issue for this on nightwatch repo, although am not sure if it is an issue with nightwatch or something deeper.
The HTML content to be tested looks something like:
<body>
<iframe id="top-iframe" src="about:blank">
#document
<html>
<body>
<container>
<!-- access this iframe to test -->
<iframe id="nested-iframe" src="news.google.com"></iframe>
</container>
</body>
</html>
</iframe>
</body>
Where #nested-frame will need to be accessed from the top level document for inspection of content.
The test code is using NightwatchJS, more details about config, setup and code are in the GitHub issue.
The Gist of the issue:
The problem is that to access the nested iFrame, it needs to first find #top-frame web element, use the returned web element and pass it to frame which makes the WebDriver call to change context of test session to that frame. This is all good with Chrome, FF, and Safari as they can all find this frame web element and make the switch into the frame context. My test that Safari was changing iFrame context, although not sure how good it is, was to try and find another DOM element other than the nested frame, which it could find. The problem comes when with Safari, after switching into #top-frame, it cannot find the #nested-frame web element, and Nightwatch returns a 404 no such element from the HTTP call. Strange, right?
It is very puzzling, my latest thinking was maybe it was a cross origin issue. But then I read on WebDriver switch to frame:
NOTE WebDriver is not bound by the same origin policy, so it is always possible to switch into child browsing contexts, even if they are different origin to the current browsing context.
And I also tried checking Disable Cross Origin Restrictions from Safari Developer menu.
As mentioned before, I can find another DOM element in the #top-frame. I tried things like 10-15s timeouts thinking maybe it needed to load. I can inspect the browser with debugger and see that #nested-frame is there and the content loads as expected. There are not console errors indicating any content failed to load.
It's very puzzling to me and I'm not sure how to further debug. Maybe someone else with a fresh perspective could have a suggestion or if someone has run into a similar situation as this. Throwing this out into the universe as information is limited on the topic too, so maybe this could help someone else. TIA!
iframes
As per the documentation iframe is a construct which embeds a document into an HTML document so that embedded data is displayed inside a subwindow of the browser's window. This does not mean full inclusion and the two documents are independent, and both them are treated as complete documents, instead of treating one as part of the other.
iframe structure and details
Generally, an iframe element is in the form of:
<iframe src="URL" more attributes>
alternative content for browsers which do not
support iframe
</iframe>
Browsers which support iframe display the document referred to by the URL in a subwindow, typically with vertical and/or horizontal scroll bars. Such browsers ignore the content of the iframe element (i.e. everything between the start tag <iframe...> and the end tag </iframe>). Browsers which do not support iframe (or have such support disabled) does the opposite, i.e. process the content as if the <iframe...> and </iframe> tags were not there. Thus, the content matters, despite being ignored by some browsers.
This usecase
As the top-level <iframe> is having src="about:blank" it is highly unlikely there can be any child <iframe>. Hence, in absence of any child <iframe> your attempt to access any nested <iframe> will fail.
Reference
You can find a relevant detailed discussion in:
Ways to deal with #document under iframe
After discussion with Selenium team, this appears to be a bug with Apple.
I have filed a ticket with Apple here.

Programmatically inject custom script into page body at runtime - like Browser Link

I'm looking for a way to inject a custom script into the _Layout.cshtml purely from code. _Layout.cshtml cannot know anything about it. Just like Browser Link does it.
You simple write this:
app.UseBrowserLink();
And this gets injected into the body at runtime.
<!-- Visual Studio Browser Link -->
<script type="application/json" id="__browserLink_initializationData">
{"requestId":"a717d5a07c1741949a7cefd6fa2bad08","requestMappingFromServer":false}
</script>
<script type="text/javascript" src="http://localhost:54139/b6e36e429d034f578ebccd6a79bf19bf/browserLink" async="async"></script>
<!-- End Browser Link -->
</body>
There is no sign of it in _Layout.cshtml.
Unfortunately Browser Link isn't open source so I can't see how they have implemented it. Browser Link source now available
So I was wondering how it was done?
It's not open source, but you can easily decompile it to see how it works.
From a comment in the source code:
This stream implementation is a passthrough filter. It's job is to add links to the Browser Link connection scripts at the end of HTML content. It does this using a connection to the host, where the actual filtering work is done. If anything goes wrong with the host connection, or if the content being written is not actually HTML, then the filter goes into passthrough mode and returns all content to the output stream unchanged.
The entire thing seems pretty involved, but doesn't seem to use anything not available out of the box, so I guess it can be possible to code a similar thing.
Razor allows you to do this quite easily - you can even use a flag.
Example:
In your controller:
ViewData["RegisterCustomCode"] = "true";
In your View (.cshtml):
#if (ViewData["RegisterCustomCode"] == "true")
{
<text>
<script src="..."></script>
</text>
}

selenium: test "disable on submit" behavior

We're using Selenium WebDriver to test a form that has a double-post prevention behavior. There's some simple javascript that disables the button upon click, so that users won't accidentally post the same thing twice.
How do we test this?
The issues is that the button.click() blocks until the next page has loaded, at which point we certainly can't assert anything about the button on the previous page. Even if we were to somehow get the .click() to be non-blocking, there's an inherent race condition; if the browser/javascript is much faster than the test system, it will be able to unload the page before the test can assert anything about the button.
Bonus points for solutions without javascript injection hacks.
Based on the assumption that Esc cancels page loading in every browser and OS, this should work:
WebElement input = driver.findElement(By.tagName("input"));
input.sendKeys(Keys.ENTER, Keys.ESCAPE);
Assert.assertFalse(input.isEnabled());
It sends Enter and Esc to the button in rapid succession, so that the JavaScript is fired, but the page load has no chance of kicking in. The only problem I can see is that you won't be able to get to the next page with this test unless you refresh and send a new form. But we should only test one feature at a time anyway, so you're fine ;-).
EDIT (to address your comment)
Actually, yes! You can try to se send a click and the Esc key at the same time via The Advanced User Interactions API (JavaDocs). You can also achieve a nonblocking click this way.
Anyway, this approach still sends two requests which isn't the fastest imaginable thing to do, but it (sometimes barely) passes my test, so you might give it a try:
WebElement input = driver.findElement(By.tagName("input"));
new Actions(driver)
.click(input)
.sendKeys(input, Keys.ESCAPE)
.perform();
Test environment: IE8 and FF18 with a locally stored file and Selenium 2.29.1; Win XP SP3.
The test file looks like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
<a href="http://google.com/">
<input type="button" value="Hello." onclick="this.disabled='true';" />
</a>
</body>
</html>

Dojo/Dijit SimpleTextarea and RadioButton (with Spring-JS integration) validation via 'required' attribute not supported, yet works in FireFox?

I'm having some issues with integrating the DOJO javascript library with Spring framework. Specifically, the problem is how to validate textareas and radiobuttons. I am using Spring-Js library to decorate standard html form elements e.g.
<form:input path="actionDescription" id="actionDescriptionId"/>
<script type="text/javascript">
Spring.addDecoration(new Spring.ElementDecoration({
elementId : "actionDescriptionId",
widgetType : "dijit.form.SimpleTextarea",
widgetAttrs : { disabled : false,
required: true,
rows: "4",
cols: "60",
placeHolder: "Enter description of fault",
style: "width:auto;height:50px;"
}}));
</script>
I have been developing in FireFox (using Firebug) and I've only now realised (after looking at the Dojo/Dijit documentation) that dijit.form.SimpleTextArea doesn't support the 'required' attribute. I never checked this before as it all worked fine in FireFox. I have a form button which when clicked will validate all decorated elements, and in firefox all components including text areas and radiobuttons will pop up with a nice looking tooltip indicating the field is required. The line of code is use is this:
<script type="text/javascript">
Spring.addDecoration(
new Spring.ValidateAllDecoration({elementId:'proceed', event:'onclick'}));
</script>
This is great as it prevents forms submission until all required fields are completed. The radiobuttons pop up with a nice message saying the user must select one of the options, and the text area pops up with a nice message telling the user to type something. However, it doesn't work in Safari or IE. Validation doesn't work for text areas and radiobuttons on these other browsers, and so server side validation is used to redirect the user back to the form. Although this works, I much prefer to prevent form submission in the first place and have consistent error reporting rather than a mix of client and server side error messages.
I'm really struggling to understand why it works in firefox when the dijit textarea components aren't supposed to support the 'required' attribute? I like the idea of using the spring-js to enhance basic components, but I don't really understand how decorating an element with digit.form.SimpleTextarea with validation works in FireFox when according to the digit documentation, there isn't any supported validation?
I was wondering if any other Spring developers who use the Spring-Js/Spring-DOJO integration have come across this behaviour and if they have any deeper understanding of how it works. What I really want is to have the textareas validated in all browsers including IE.
Ok, so the issue was with HTML5 in Firefox providing the validation behaviour for textareas and radiobuttons. Since my target audience is IE (and possibly IE6), I can't rely on HTML5 form validation, and therefore I'm stuck with the fact that DOJO's Dijit widgets for textareas and radiobuttons don't support validation.
Thanks to http://www.harelmalka.com/?p=137 I have created a workaround to enable validation on textareas. For radiobuttons however, I have provided a default selection to negate the need for validation.

colorbox with address bar

I am a javascript dummy. I downloaded colorbox and jquery. They work great. I followed tutorials and read the example code but I cant figure this out.
When I open a colorbox ,it opens to the correct url, I can then click links in the box and surf other sites. That is all great. I need to have the url show in a address block at the top of the window. When I use a java popup it will work fine. You can goto other urls and the address shows in the address bar at the top of the window.
So I assume that I can do it with colorbox. This would make my page look much better than a plain popup. Can this be done. here is my code.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"> </script>
<script src="http://www.mysite.com/colorbox/jquery.colorbox.js"></script>
<link rel="stylesheet" href="http://www.mysite.com/colorbox/colorbox.css" />
<script>
parent.jQuery.colorbox.close();
$(function ()
{
$(".iframe").colorbox({iframe:true, width:"80%", height:"80%"});
})
</script>
and my link to open the box
<a class='iframe' href="http://www.ebay.com">ebay </a></p>
If you chooes to help I beg you to show me where the new code go's. If you tell me to add a line of code I will not understand where to put it. I am trying hard to learn javascript but I am a very newbe. Thanks.
I don't think ColorBox is the right plugin for you to use, given its default design and your skill set. ColorBox is not designed to be "browser like" and let the user surf to other sites.
It is possible to change that design assumption, but it would require more advanced JS skills than you admit to.
Maybe you can achieve your aim by simply opening a new browser instance using a plain HTML anchor tag (<a>) and using the "target=" parameter.
Best,
KJM