Hi I am using selenium webdriver 2.25.0 & faceing the some serious issues,
how to find broken images in a page using Selenium Webdriver
How to find the image is replace by another image having same name (This is also bug) using webdriver.
Thanks in advance for your value-able suggestions.
The accepted answer requires that you use a proxy with an extra call to each image to determine if the images are broken or not.
Fortunately, there is another way you can do this using only javascript (I'm using Ruby, but you can use the same code in any executeScript method across the WebDriver bindings):
images = #driver.find_elements(:tag_name => "img")
broken_images = images.reject do |image|
#driver.execute_script("return arguments[0].complete && typeof arguments[0].naturalWidth != \"undefined\" && arguments[0].naturalWidth > 0", image)
end
# broken_images now has an array of any images on the page with broken links
# and we want to ensure that it doesn't have any items
assert broken_images.empty?
To your other question, I would recommend just taking a screenshot of the page and having a human manually verify the resulting screenshot has the correct images. Computers can do the automation work, but humans do have to check and verify its results from time to time :)
The next lines are not optimized, but they could find broken images:
List<WebElement> imagesList = _driver.findElements(By.tagName("img"));
for (WebElement image : imagesList)
{
HttpResponse response = new DefaultHttpClient().execute(new HttpGet(image.getAttribute("src");));
if (response.getStatusLine().getStatusCode() != 200)
// Do whatever you want with broken images
}
Regarding your second issue, I think I didn't understand it correctly. Could you explain it with more detail?
Based on the other answers, the code that eventually worked for me in an angular / protractor / webdriverjs setting is:
it('should find all images', function () {
var allImgElts = element.all(by.tagName('img'));
browser.executeAsyncScript(function (callback) {
var imgs = document.getElementsByTagName('img'),
loaded = 0;
for (var i = 0; i < imgs.length; i++) {
if (imgs[i].naturalWidth > 0) {
loaded = loaded + 1;
};
};
callback(loaded);
}).then(function (loadedImagesCount) {
expect(loadedImagesCount).toBe(allImgElts.count());
});
});
The webdriver code counts the number of img elements, and the function executed within the browser context counts the number of successfully loaded elements. These numbers should be the same.
Why doesn't this work?
var spans = $();
var elem = document.getElementById('someId');
spans.add(elem);
What is the proper way to start off with an empty collection and add elements to it?
I want to loop through a collection of ids and find the element on the page and add it to the matched set.
Quoting from the jQuery website:
Given a jQuery object that represents a set of DOM elements, the .add() method constructs a new jQuery object from the union of those elements and the ones passed into the method.
Hence, when you do .add() it will not save the added elements, you would have to explicitly assign the element to the newly created object i.e
var $elements = $('.elements');
$elements = $elements.add($('#anotherelement'));
The .add() method returns a new jQuery object, so you'd need to overwrite the old one:
spans = spans.add( elem );
...or since you're adding DOM elements, you can modify the existing jQuery object with .push().
spans.push( elem );
EDIT: Changed .pushStack() to .push(), though I don't know if .push() is officially supported.
You could use .pushStack() to add a collection though.
spans = spans.pushStack( [elem] );
or
spans = spans.pushStack( document.getElementsByTagName('div') );
I guess I don't get what you're asking. If you have an element and you want to add it to a collection, you just use the .add() method just like you've already shown. What confuses some is that this returns a new jQuery object so you would do it like this:
var spans = $();
var elem = document.getElementById('someId');
spans = spans.add(elem);
Of course, something like this would be shorter:
var spans = $();
spans = spans.add('#someId');
And, of course, you don't have to start with an empty object. You would just start with:
var spans = $('#someId');
If you're looking to push or add items selected from a jQuery object, you could also do this:
var $els = $(),
$someEls = $(".some-els");
$els.push.apply($els, $someEls);
Just another way to do it.
What you actually want to do is use jQuery to it's full potential. You can use selectors to grab and create the collection right away. Your three lines above becomes one line:
var spans = $('#someId');
to add more ids to the collection, you can separate them with commas:
var spans = $('#someId1, #someid2, #someid3');
There may be better ways to do what you're trying, but if you just want to create an empty jQuery object, use this:
var $foo = $([]);
Edit: I should clarify - your code actually should work, unless you're using an older version of jQuery, in which case $() would create a collection containing the document object. In newer versions, however, there's nothing wrong with that. The code snippet I pasted above is just something that should work in older versions and newer versions of jQuery.
Edit 2: In response to this portion of the question: "I want to loop through a collection of ids and find the element on the page and add it to the matched set", the following code might be useful:
var ids = ['foo', 'bar', 'baz'],
selector = $.map(ids, function(i, id) {
return '#' + id;
}).join(','),
$collection = $(selector);
While this doesn't directly answer the question of "how to append to an existing jQuery selection", I have a work-around for this particular use-case.
You can pass an array of DOM elements to jQuery, and it will create a jQuery selection out of them.
var spansArray = [];
var elem = document.getElementById('someId');
spansArray.push(elem);
var spans = $(spansArray);
I can't think of any reason why you would need to add each element to the jQuery selection one-at-a-time, as opposed to all-at-once, so this should be a "drop-in-replacement" for your use case. In theory, this must also prove more efficient, as jQuery's .add() is ultimately just calling .push() on some array behind the scenes.
Try
var spans = $("<span />");
var elem = $("#someId").html();
spans.append(elem).appendTo('#someAnotherId');
instead
The reason your code doesn't work is because add does not change the collection, it returns a new jQuery object with the new elements in it. If you wanted, you could instead say spans = spans.add(elem);, but what you're doing is unnecessary: the beauty of jQuery is that it makes this sort of imperative programming unnecessary. Look at helloandre's answer for a much easier way to accomplish your goal.
It's like the following, if this makes sense:
var x = [1, 2, 3];
x.concat(4);
console.log(x); // [1, 2, 3] -- concat does not mutate the original array
i am trying to figure out if i can in anny way get the exact position for every character inside a textflow?, also I'm having trouble with the TLF documentation, is there anny documentation that shows more on how to work with it in actionscript rather than mxml, im looking to write my own component and perhaps not use richtexteditor if i don't need to.
Many thanks!
Edit: i finally think i figured out how to get each characters position in the textflow:
private function getCharPosition():void {
for (var i:int=0; i<=textController.flowComposer.numLines; i++) {
var textFlowLine:TextFlowLine = textController.flowComposer.findLineAtPosition(i);
var textLine:TextLine = textFlowLine.getTextLine();
trace('number of atoms in this line: ' + textline.atomCount);
for (var j:int=0; j<=textLine.atomCount; j++) {
try {
trace(textLine.getAtomBounds(j));
} catch (e:Error) {
trace('error');
}
}
}
}
This returns an error that's why i have try and cache, i have tried to change textLine.atomCount to -1 but that wont work either. Now i don't know what character exactly that i have the position for. Lots of figuring out yet...
You can use some of these steps which (among other things) allow to determine character's bounds.
What about your second question you can refer to the following documentation and/or some samples.
We need to be able to handle a "playable" (play/pause/seek) effect in which the nature of the effect cannot be determined at compile time.
The problem we are running into is resetting the target(s) state after the effect has completed. If we manually drag the seek slider back to the beginning, everything works fine. However, if we set the playheadTime of the composite effect back to 0, the effected targets retain their original value until the playheadTime gets to the correct position to effect the target.
Here is a simplified (as much as I could) test case with view source enabled:
http://www.openbaseinteractive.com/_tmp/PlayableEffectTest/
The problem is demonstrated if you let it play to the end, and then hit the play button to start it over.
What is the best way to go about manually resetting the target values given that the exact nature of the effect is unknown?
Many thanks for your time!
edit
I forgot to mention we are using Flex 4.5 preview release.
Have you tried:
effect.reverse()
More info
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/effects/IEffect.html
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/effects/IEffect.html#reverse()
Well it's a little kludgy, but I was able to accomplish this by calling some internal methods on the effect to capture the start values, then assigned those values to the targets on a reset.
import mx.core.mx_internal;
use namespace mx_internal;
private var _propertyChangesArray:Array;
protected function captureStartValues(effect:Object):void
{
effect.captureStartValues();
_propertyChangesArray = effect.propertyChangesArray;
}
protected function reset(effect:Object):void
{
for each(var change:PropertyChanges in _propertyChangesArray)
{
var target:Object = change.target;
for(var p:String in change.start)
{
if(target.hasOwnProperty(p))
{
var startVal:* = change.start[p];
var endVal:* = target[p];
if(!isNaN(startVal) && startVal != endVal)
{
target[p] = startVal;
}
}
}
}
effect.playheadTime = 0;
}
I don't know if this is the best way to accomplish this, but it seems to be working so far. I am absolutely open to suggestions for a better method.
Cheers!
I have and ASP.NET 3.5 page where I need to debug some JavaScript code.
function checkAll(isChecked)
{
debugger;
var dataGridElements = document.getElementById('" + DataGridSearchResults.ClientID + #"').getElementsByTagName('input');
for (var i = 0; i < dataGridElements.length; i++)
{
var e = dataGridElements[i];
if ((e.type=='checkbox') && (!e.disabled))
{
e.checked = isChecked;
}
}
}
As you can see, I added a debugger statement in the first line. For some reason, when i execute the page, the javascript (which is in a string variable and registered with Page.ClientScript.RegisterClientScript statement) is in my source code twice! The second block doesn't have my debugger statement either! I checked the project, this block of Javascript is only listed once in the project.
Any ideas? (the client i am running on is IE8 if that makes a difference)
Figured it out. The base page that this control was on (the javascript was in an ASCX file) was a page that had a tab strip on it. One of the other tabs had the code copy and pasted with the exact same signature, just a grid name difference. Once i changed the signature on my set of code, it worked fine.