I'm using watin to automate a process on a web system (internal).
I can open the website and access some links, but others cannot be found. I think this may be either because they are deeply nested or because the href is javascript. This is the format they are in:
<frame>
<html>
<frameset>
<frame>
<html>
<body>
<div>
<table>
<table>
<tr>
<td>
<a id="1_1_1_a" href="javascript:blah" </a>
I've tried various different ways to find by id, element type etc. But I'm stuck on this.
Can anyone help?
Thanks
Elements within a frame have to be searched through its frame because each frame is considered a separate namespace in WatIn. So first get the correct frame (by calling the Frame method or through the Frames property - note that in your example you must do it twice as you have two nested frames) and then search for the link, e.g.:
ie.Frames[0].Frames[0].Link("1_1_1_a")
Try this
using (var browser = new IE("your_web_site_here"))
{
try
{
Frame first_frame = browser.Frame(Find.ById("frame_1_id"));
Frame second_frame = first_frame.Frame(Find.ById("frame_2_id"));
var first_div = second_frame.Div(Find.ById("first_div_id"));
Assert.IsTrue(first_div.Exists);
var Link_to_click = first_div.Link(Find.ById("1_1_1_a"));
Assert.IsTrue(Link_to_click.Exists);
Link_to_click.Click();
}
catch (Exception ex)
{
}
}
Sometimes watin cannot find elements I'm still trying to find out why and what are the preconditions.
I had a similar issue where my test would browse to a page that had 40 links on it and even though you could see all the links on the page the following statement would show links (and other elements collections) had a count of zero.
ie.Links.Count();
I'm still not sure exactly what the underlying issue is but I discovered that if you start Gallio Icarus / Gallio Echo / Visual Studio (or whatever test runner you are using) by Right Click -> Run as administrator the test works as expected and the elements are loaded into the ie browser object correctly.
Related
I'm developing a web browser on Android and want to show the URL logo for the most visited sites like in Chrome (4 X 2). But the problem is that most favicons (eg: http://www.bbc.co.uk/favicon.ico) are of size either 16X16 or 32X32 and they don't look good when scaled up.
Is there a way I can download a high resolution icon/bitmap for an URL in a standard way? How about opening the home page and then extracting all the image links and then choose an image with the name logo in it? Would this method work for all the URLs? I want to know if there is a standard way to obtain a high resolution icon for a given URL or favicon is the only standard way to get the website logo?
You can code it yourself or use an existing solution.
Do-it-yourself algorithm
Look for Apple touch icon declarations in the code, such as <link rel="apple-touch-icon" href="/apple-touch-icon.png">. Theses pictures range from 57x57 to 152x152. See Apple specs for full reference.
Even if you find no Apple touch icon declaration, try to load them anyway, based on Apple naming convention. For example, you might find something at /apple-touch-icon.png. Again, see Apple specs for reference.
Look for high definition PNG favicon in the code, such as <link rel="icon" type="image/png" href="/favicon-196x196.png" sizes="196x196">. In this example, you have a 196x196 picture.
Look for Windows 8 / IE10 and Windows 8.1 / IE11 tile pictures, such as <meta name="msapplication-TileImage" content="/mstile-144x144.png">. These pictures range from 70x70 to 310x310, or even more. See these Windows 8 and Windows 8.1 references.
Look for /browserconfig.xml, dedicated to Windows 8.1 / IE11. This is the other place where you can find tile pictures. See Microsoft specs.
Look for the og:image declaration such as <meta property="og:image" content="http://somesite.com/somepic.png"/>. This is how a web site indicates to FB/Pinterest/whatever the preferred picture to represent it. See Open Graph Protocol for reference.
At this point, you found no suitable logo... damned! You can still load all pictures in the page and make a guess to pick the best one.
Note: Steps 1, 2 and 3 are basically what Chrome does to get suitable icons for bookmark and home screen links. Coast by Opera even use the MS tile pictures to get the job done. Read this list to figure out which browser uses which picture (full disclosure: I am the author of this page).
APIs and open source projects
RealFaviconGenerator: You can get any web site favicon or related icon (such as the Touch Icon) with this favicon retrieval API. Full disclosure: I'm the author of this service.
BestIcon: Although less comprehensive, Besticon offers a good alternative, especially if you want to host the code yourself. There is also a hosted version you can use right away.
The Go code at https://github.com/mat/besticon tries to solve this problem.
For example
$ besticon http://github.com
http://github.com: https://github.com/apple-touch-icon-144.png
There is also an accompanying hosted version of the code, see for example http://icons.better-idea.org/icons?url=github.com.
(Disclaimer: I wrote it because I needed to solve the same problem a while ago.)
another option is getting favicons from any domain using a hidden google API
the favicon link pattern will be
https://www.google.com/s2/favicons?domain={domain}&sz={size}
for example
https://www.google.com/s2/favicons?domain=stackoverflow.com&sz=64
Logos are not going to be consistently named and very difficult to identify consistently. Consider putting the favicon on a colour tile of suitable dimensions. People will quickly associate the colour with the website. You could either extract a dominant colour from the website or favicon using something like colorthief, or make each one unique using a golden angle formula to choose a hue.
Here is a new and genuine solution which will always give you the best results-
Webchromeclient gives a callback of onReceivedTouchIconUrl method for all the websites just hold the url from here.
Next step is to convert this url to bitmap which can be done like this-
try {
URL url = new URL(touchiconUrl);
HttpURLConnection connection =
(HttpURLConnection)url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
Next step is to send this bitmap for the shortcut.
Note: Remember to create bitmap on background thread like asynctask.
This HTML document requires a base url and the HTML/"View Page Source" of the web page and should output the values.
<!doctype html>
<input type=text placeholder=URL><br>
Place "View Page Source" of HTML homepage<br>
<textarea id=HTML placeholder="HTML content of webpage">
</textarea><br>
<input type=Submit>
<script>
function url(u,n){
try{
u = u.getAttribute(n);
}
catch(e){
return 'null';
}
if(u.slice(0,2) == "//"){
u = "http:"+u;
}
else if(u.slice(0,1) == "/"){
u = u.slice(0,1);
}
return '<img src="'+u+'">';
}
document.querySelector('input[type=Submit]').onclick = function(){
var output = '';
var HTML = document.getElementById('HTML').value;
var doc = document.implementation.createHTMLDocument("New Document");
doc.documentElement.innerHTML = HTML;
output = output + "apple-touch-icon<br>"+url([].slice.apply(doc.querySelectorAll('link[rel="apple-touch-icon"]')).reverse()[0],'href')
// deprecated output = output + "apple-touch-icon-precomposed<br>"+url([].slice.apply(doc.querySelectorAll('link[rel="apple-touch-icon-precomposed"]')).reverse()[0],'href')
output = output + "<br>image/png<br>" + url(doc.querySelectorAll('link[rel="icon"][type="image/png"]')[0],'href');
// <meta name="msapplication-TileImage" content="/mstile-144x144.png">
// deprecated output = output + "<br>msapplication-Ti:<br>"+ url(doc.querySelectorAll('link[name="msapplication-TileImage"]')[0],'content');
// <meta name="msapplication-config" content="/browserconfig.xml/ ">
//output = output + "<br>msapplication-con: "+ url(doc.querySelectorAll('meta[name="msapplication-config"]')[0],'content');
// <meta property="og:image" content="http://somesite.com/somepic.png"/>
output = output + "<br>og:image<br>" + url(doc.querySelectorAll('meta[property="og:image"]')[0],'content');
// <link rel="image_src" href="https://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon.png?v=c78bd457575a">
output = output + "<br>image_source<br>" + url(doc.querySelectorAll('link[rel="image_src"]')[0],'href');
var URL = window.location.hash;
document.getElementById('output').innerHTML = output;
};</script>
<div id=output></div>
If you would like to automate the retrieval of the HTML you could use something like the following for PHP.
<? echo file_get_contents($_GET["url"]);
Usually favicon is small (like 16x16 or 32x32). If you need bigger dimensions, extract not favicon, but logo from homepage/header.
I have this problem I'm facing. I have been working on a project using Grails based on the advice from a friend. I'm still a novice in using Grails, so any down to earth explanation would be highly welcomed.
My project is a web application which scans broken or dead links and displays them on a screen. The main application is written in Java, and it displays the output (good links, bad links, pages scanned) continuously on the system console as the scan goes on. I've finished implementing my UI, controllers, views, database using Grails. Now, I will like to display actively in a section of my GSP page say forager.gsp the current link being scanned, the current number of bad links found and the current page being scanned.
The attempts I have tried in implementing this active display include storing the output my application displays on the console in a table in my database. This table has a single row which is constantly updated as the current paged scanned changes, number of good links found changes and number of bad links found changes. As this particular table is being updated constantly, I've written an action in my controller which reads this single line and renders the result to my UI. The problem I'm now facing is that I need a way of constantly updating the result being displayed after an interval of time in my UI. I want the final output to look like
scanning: This page, Bad links: 8, good links: 200
So basically here is my controller action which reads the table from the database
import groovy.sql.Sql
class PHPController {
def index() {}
def dataSource
def ajax = {
def sql = new Sql(dataSource)
def errors = sql.rows("SELECT *from links")
render (view: 'index', template:'test', model:[errors:errors])
}
}
Here is the template I render test.gsp
<table border="0">
<g:each in="${ errors }" var="error">
<tr><td>${ error.address }</td><td>${ error.error}</td><td>${ error.pageLink}</td></tr>
</g:each>
</table>
For now I'm working with a test UI, which means this is not my UI but one I use for testing purposes, say index.gsp
<html>
<body>
<div><p>Pleaseeee, update only the ones below</p></div>
<script type="text/javascript">
function ClickMe(){
setInterval('document.getElementById("auto").click()',5000);
alert("Function works");
}
</script>
<div id="dont't touch">
<g:formRemote url="[controller:'PHP', action:'ajax']" update="ajaxDiv"
asynchronous="true" name="Form" onComplete="ClickMe()" after="ClickMe()">
<div>
<input id="auto" type="button" value="Click" />
</div>
</g:formRemote>
<div id="ajaxDiv">
<g:render template="/PHP/test"/>
</div>
</body>
</html>
The div I'm trying to update is "ajaxDiv". Anyone trying to answer this question can just assume that I dont have an index.gsp and can propose a solution from scratch. This is the first time I'm using Grails in my life so far, and also the first time I'm ever dealing with ajax in any form. The aim is to dynamically fetch data from my database and display the result. Or if someone knows how to directly mirror output from the system console unto the UI, that will also be great.
It sounds like a form would be appropriate for your needs. Check out the Grails documentation on forms. You should be able to render a form with the values you would like without too much trouble. Be sure to pay attention to your mapping and let me know if you have any questions after you have set index.gsp up to render a form for your values.
Selenium Webdriver. Looking to Locate New Article from following code. Please note this is under an iframe.
<img class="rtbIcon" src="/icons/16/app/shadow/document_add.png" alt="">
<span class="rtbText">New Article</span>
I have tried to locate with xpath and many other ways. But following is what I get everytime
Code : driver.findElement(By.xpath("id('RadToolBar1'):div:div:div:ul:li[3]:a:span:span:span:span"));
Result:
The given selector id('RadToolBar1'):div:div:div:ul:li[3]:a:span:span:span:span is either invalid or does not result in a WebElement. The following error occurred:
New article has no name, id so please if some one can help find me solution.
Your xpath seems to be wrong. The best way to get the xpath for any element on a page is by installing mozilla add on - Fire Bug. You can inspect any element using this add on and also copy the correct xpath of your element present on the page.
This should be your xpath -
driver.findElement(By.xpath("//*[#class='rtbText']"));
or
driver.findElement(By.linkText("New Article"));
One of these should work. Let me know if you face any problem.
I have a strange result happening when loading a Partial View using jQuery Ajax into the DOM, but only when viewing the result using IE8.
The Partial View in question (for example purposes only) looks like this;
<aside>Example test</aside>
When the result comes back from the Ajax call it appears to look exactly as above. However when viewing the DOM using the developer tools in IE8 the result looks like this;
<aisde/>
Example test
</aside/>
As a result the element is not recognised and the text does not sit within it. Also the style sheet class for 'aside' is not being applied. This only happens in IE8 as far as I can see.
Any one got any suggestions, other than do not use custom tags?
Thanks in advance
You need to make sure the DOM recognizes HTML5 elements. Essentially you will have to do:
document.createElement('aisde');
Have a look at this link. Without creating the element older IE browsers will not see or style the elements.
The common practice around these issues is to load a html5 fix javascript file within a conditional comment block. The script does a createElement on all new html5 node types.
<!--[if lte IE 8]>
<script src="html5.js" type="text/javascript"></script>
<![endif]-->
I am having a strange issue in Firefox 3.5.2 with F5 refresh.
Basically, when I focus on an input field and hit f5 the contents of that input field gets copied to the next form field after the F5 refresh.
But, if you inspect the HTML source code, the values are correctly loaded.
I am not having this issue in IE8 or Safari 4.0.3.
The problem does not occur if I do a hard refresh or run window.location.refresh(true).
After F5 Refresh: http://i805.photobucket.com/albums/yy339/abepark/after.jpg
Here's an overview of what's going on.
I believe the thing you should look into is the autocomplete attribute,
you should set it to off on the input box. However be careful since this will trigger two effects.
When you refresh the page it won't remember the old values
The default dropdown of the already used values on that input box will also be disabled.
If you want to keep the second behavior you should set the autocomplete attribute back to on with JS.
Browsers can remember form field contents over a refresh. This can really throw your scripting off if it is relying on the initial value of a field matching what's in the HTML. You could try to prevent it by calling form.reset() at the start.
Different browsers have different strategies for detecting when a form or a field is the same as in the previous page. If you have clashing names, or names that change on reload, it is very possible to end up confusing them. Would have to see some code to work it out for sure.
In the backend, I am using ASP.NET MVC 1.0 with the Spark View engine. When I examine the source code after an F5 refresh in Firefox 3.5.2, the page renders correctly; however, if you look at the page visually the adjacent form field field gets populated with the value from the previous field.
I included enough code so you can just get an idea of what I'm trying to do.
Again, the rendering is fine and the final view/HTML code is fine. It's what I see on the screen that is incorrect. I am using hidden vars; but the issue occurred before using it as well.
Note in the code below, I have 2 distinct ID fields: "date_{projectTask.ProjectTaskId}" and "finishDate_{projectTask.ProjectTaskId}, which gets renders to something like "date_1" and "finishDate_2".
<table>
<for each="ProjectTask projectTask in projectTasksByProjectPhase">
<input type="hidden" value="${projectTask.ProjectTaskId}" />
<tr>
<td class="date">
<div class="box">
<div class="datefield">
<input type="text" id="date_${projectTask.ProjectTaskId}" value="${startDate}" /><button type="button" id="show_${projectTask.ProjectTaskId}" title="Show Calendar"><img src="~/Content/yui/assets/calbtn.gif" width="18" height="18" alt="Calendar" ></button>
</div>
</div>
</td>
<td>
<div class="box">
<div class="datefield">
<input type="text" id="finishDate_${projectTask.ProjectTaskId}" value="${finishDate}" /><button type="button" id="finishShow_${projectTask.ProjectTaskId}" title="Show Calendar"><img src="~/Content/yui/assets/calbtn.gif" width="18" height="18" alt="Calendar" ></button>
</div>
</div>
</td>
</tr>
</for>
</table>
FYI: ${} are used to output variables in the Spark View engine.
I am also using the YUI 2.7 Connection to make Ajax calls to update the datebase for "change" and "enter/tab key press" events. I am able to verify that the AJAX calls are made correctly and the form field values are still valid.
The problem occurs when I just do a F5 refresh; for some reason, the "finishDate_1" gets populated with the value from "date_1".
This problem occurs just by clicking on "date_1" and hitting F5; so, the adjacent field just gets populated even if there are no AJAX calls.
Here's the Javascript code I call towards the end of the body"
YAHOO.util.Event.onDOMReady(
function() {
var idList = YAHOO.util.Dom.getElementsBy(function (el) { return (el.type == 'hidden'); }, 'input');
len = idList.length;
var startDatePickers = new Array();
var finishDatePickers = new Array();
for (var i = 0; i < len; i++) {
var id = idList[i].value
startDatePickers[i] = new DatePicker("date_" + id, "show_" + id, "cal_" + id);
startDatePickers[i].valueChanged.subscribe(updateDate, 'S');
finishDatePickers[i] = new DatePicker("finishDate_" + id, "finishShow_" + id, "finishCal_" + id);
finishDatePickers[i].valueChanged.subscribe(updateDate, 'F');
}
}
}
The form field gets copied over before any Javascript code is processed because I call the Javascript code towards the end of the body after all HTML is rendered. So, I'm guessing it's a refresh issue in Firefox? What do you guys think?
As you can see above, I created my own calender date picker objects which allows you to either enter the date in the text manually or by clicking on a button to view the calendar and select a date. Once you enter or select the date, an AJAX call will be made to update the datebase in the back end.
Thanks everybody for the quick responses.
#Anonymous: whoever you are, you are awesome!
#bobince: thanks for the feedback as well.
I added a dummy form tag with the attribute autocomplete="off" and that solved the problem!
I was scratching my head because I didn't get this issue in Safari 4.0.3 or Internet Explorer 8.
<form action="" autcomplete="off">
<!-- my code -->
</form>
The values were loading correctly in the back end (ASP.NET MVC 1.0/Spark View engine) and the HTML source code reflected this, but the input field values were not getting populated correctly. I was using the YUI Connection Manager and Javascript to support edit-in-place and the date pickers.
I tried changing the XHR call to a GET call instead of POST and the same issue was happening.
Anyway, the problem was that the Firefox was not setting the correct values for the input fields for F5 refreshes.
Again, thanks so much! You guys rock!
All element id's must be unique, if two elements have same id's then that could be reason why Firefox inserts same values to elments that didn't orginally have those values entered.
I had a similar problem related to my question at Input control shows incorrect value, even 'though inspect element shows the right value is there
The problem occurred for me in Firefox, but not Chrome, for some but not all controls on the form, and when I pressed F5, but not ctrl-F5.
The "dummy form" seems to have resolved it for me.