There is a thing: I have an element which I need to select using their src attribute, but the src attribute is like this:
src = "https://xyz.amazonaws.com/c95eb334-e9ae-43c3-a75d-e926efa4661e/wardrobe/1601210284_bag-thumbnail.jpg?AWSAccessKeyId=AKIAVQ6TQWKMM4EMM232&Expires=1626957604&Signature=d3ITnIQDEvIk3UknRjEMuglUF0I%3D"
I am interested with this part: "1601210284_bag-thumbnail.jpg". The last part of the src is changing with every login/logut so I can't just make an assertion for all the src value.
Is there any way to select the element using only part of the src attribute? Any Ideas?
EDIT: I found that jQuery has somethig like attribute-contains-selector like this: [attr*=value]. Is there any similar in testcafe?
See if this helps
Array.from(document.querySelectorAll('img')).filter(function(x) {
console.log(new String(x.src).replace(/^.*[\\\/]/, '').split('?')[0]);
}) ;
<img src = "https://xyz.amazonaws.com/c95eb334-e9ae-43c3-a75d-e926efa4661e/wardrobe/1601210284_bag-thumbnail.jpg?AWSAccessKeyId=AKIAVQ6TQWKMM4EMM232&Expires=1626957604&Signature=d3ITnIQDEvIk3UknRjEMuglUF0I%3D">
<img src = "https://xyz.amazonaws.com/c95eb334-e9ae-43c3-a75d-e926efa4661e/wardrobe/asdsad-thumbnail.jpg?AWSAccessKeyId=AKIAVQ6TQWKMM4EMM232&Expires=1626957604&Signature=d3ITnIQDEvIk3UknRjEMuglUF0I%3D">
In your case, you could make use of the withAttribute() method as in the following in order to select the HTML element that you desire to:
import Selector from "testcafe";
const mySelector = Selector("img").withAttribute("src", /1601210284_bag-thumbnail.jpg/i);
This assumes, that you are trying to target an img element. If you target a div or any other element, you would need to replace the content within the Selector accordingly. The withAttribute method takes two arguments, the attribute of HTML element that you want to target as well as its value. For both arguments, the values can be supplied as either as a string or a regex. In this case, I supplied the attribute as a string and its value as a regex.
Related
I'm using Selenium to try and get some elements on a web page but I'm having trouble getting the ones I want. I'm getting some, but they're not the ones I want.
So what I have on my page are five divs that look like this:
<div class="membershipDetails">
Inside each one is something like this:
<div class="membershipDetail">
<h3>
VIP Membership
</h3>
</div>
They DO all have this same link, but they don't have the same text ('VIP Membership' would be replaced by something else)
So the first thing was to get all the divs above in a list. This is the line I use:
listElementsMembership = driver.find_elements_by_css_selector(div[class^='membershipDetail'])
This gives me five elements, just as I would expect. I checked the 'class' attribute name and they are what I would expect. At this point I should say that they aren't all EXACTLY the same name 'membershipDetail'. Some have variations. But I can see that I have all five.
The next thing is to go through these elements and try and get that element which contains the href ('VIP Membership').
So I did that like this:
for elem in listElementsMembership:
elemDetailsLink = elem.find_element_by_xpath('//a[contains(#href,"EditMembership")]')
Now this does return something, but it always got me the element from the FIRST of the five elements. It's as if the 'elem.find_element_by_xpath' line is going up a level first before finding these hrefs. I kind of confirmed this by switching this to a 'find_elements_by_xpath' (plural) and getting, you guessed it, five elements.
So is this line:
elemDetailsLink = elem.find_element_by_xpath('//a[contains(#href,"EditMembership")]')
going up a level before getting its results? If it is, now can I make it not do that and just restrict itself to the children?
If you are trying to find element with in an element use a . in the xpath like below:
listElementsMembership = driver.find_elements_by_css_selector(div[class^='membershipDetail'])
for elem in listElementsMembership:
elemDetailsLink = elem.find_element_by_xpath('.//a') # Finds the "a" tag with respect to "elem"
Suppose if you are looking for VIP Membership:
listElementsMembership = driver.find_elements_by_css_selector(div[class^='membershipDetail'])
for elem in listElementsMembership:
value = elem.find_element_by_xpath('.//a').get_attribute("innerText")
if "VIP Membership" in value:
print(elem.find_element_by_xpath('.//a').get_attribute("innerText"))
And if you dont want iterate over all the five elements try to use xpath like below: (As per the HTML you have shared)
//div[#class='membershipDetail']//a[text()='VIP Membership']
Or
//div[#class='membershipDetail']//a[contains(text(),'VIP Membership')]
You've few mistake in that css selector.
Quotes are missing.
^ is for starts-with, not sure if you really need that. In case it's partial matching please use * instead of ^
Also, I do not see any logic for the below statement in your code attempt.
The next thing is to go through these elements and try and get that
element which contains the href ('VIP Membership').
Code :
listElementsMembership = driver.find_elements_by_css_selector("div[class*='membershipDetail']")
for ele in listElementsMembership:
e = ele.find_element(By.XPATH, ".//descendant::a")
if "VIP Membership" in e.get_attribute('href'):
print(e.text, e.get_attribute('href'))
You can give an index using a square bracket like this.
elemDetailsLink = elem.find_element_by_xpath('(//a[contains(#href,"EditMembership")])[1]')
If you are trying to get an element using XPath, the index should start with 1, not 0.
I have a custom component called 'menu-entry':
<menu-entry v-for="field in fields" :id:"field.id" :ref="field.id" v-bind:key="field.id" v-bind:class="[classArray]" v-bind:field="field" v-on:clicked="menuEntryClicked">
</menu-entry>
I need to get one of them (for example field.id = 2) and remove an item from the classArray.
this.$refs[2] is working for HTML elements, but not for custom elements.
this.$el.querySelector isnt working either.
is there another way to remove an item from the classArray of a specific element?
Your question it is not clear but you are trying to set id and ref to field.id so following this logic it is not necessary to do though.
You can just send the id to the method you are executing like below:
<menu-entry
v-for="field in fields"
v-bind:key="field.id"
v-bind:class="[classArray]"
v-bind:field="field"
v-on:clicked="menuEntryClicked(field.id)" // <= send the id here
>
</menu-entry>
I am not sure if i helped but regarding your question, now you can figoure out which id of element is clicked and remove it from classArray or whatever you want
2 is not a valid id selector when you use document.querySelector('#2'); maybe you can use document.getElementById('2') instead - it can work.
I have an hidden input field which value changes according to the option selected in a s:select in Struts 2. Then, there's a button that points to an action like loadData.action.
I would like to add to this action a parameter named item.id with the value of the hidden field as its value, a value changing each time I select a new option.
I've tried to use an s:param with an s:property inside and the name or the id of the s:hidden, but it doesn't print the value after the = sign.
How can I do to achieve this result? loadData.action?item.id=12 where 12 is the value of s:hidden name="item" id="item" ?
Please Provide complete action link and which value to be change also your HTML structure, so it will be easy to answer your question
Assuming your HTML structure's elements, I have tried to answer your question
You can change action using jQuery on change event of your <s:select>
Have a look at https://jsfiddle.net/shantaram/qy9rew4v/
$('#id-select').change( function () {
var newAction = $('#id-form').prop('action');
newAction = newAction.substring(0, newAction.lastIndexOf('='));
$('#id-form').prop('action', newAction+"="+varItemId);
//varItemId is value of your hidden field
//which you want to change Dynamically
});
provided:
id-select -> Id of your <select> element
id-form -> Id of your <form> element
I am using
var tab = dojo.query("[widgetid^='pvr_widget_TabContainer'][0]",toolbar.domNode.parentNode)[0];
and the reason i want first element only is some of the childs are like
pvr_widget_TabContainer_0_button1 etc which holds true for my condition,
so I dont want to traverse them , can I just break the query after getting first element ?
You can use CSS selector "first-of-type" with inside the dojo.query .
Would look like this:
var tab = dojo.query("[widgetid^='pvr_widget_TabContainer']:first-of-type");
I Have a JSFIDDLE prepared for you:
http://jsfiddle.net/anmos5r8/
I'm just getting started with dojo, and I've understood that dojo.query is the same as $ in jQuery.
But I haven't figured out what it returns. Is it a specialized object like in jQuery?
What I'm trying to do (with no luck) is:
dojo.query("output").innerHTML = data;
//this doesn't work either:
dojo.query("output").html(data);
//tried accessing by id as well
dojo.query("#output").html(data);
//and tried to access a div, incase dojo has some issues with html5 elements
dojo.query("#divOutput").html(data);
And I'm currently using the new html5 elements:
<output id="output">Output goes here</output>
<div id="divOutput">non-html5 output goes here</div>
And I can't seem to find a good list on what to do with objects returned by dojo.query()..
edit: Okay, I think dojo is just messing with me now. I found this method: addContent() and that works on the above selector. But I don't want to add content, I want to replace content...
The query method returns a NodeList object.
In the ref for NodeList you can find a list of functions that you can apply to the list
of elements. There is no innerHTML function for the list, but the html function should work.
There is no "output" element in HTML, perhaps you try to target elements with the class name "output"?
dojo.query(".output").html(data)
Or the element with id "output"?
dojo.query("#output").html(data)
If you want to replace all the output tags' content with the same thing, then this code should always work:
// replace the contents of ALL <output> tags
dojo.query('output').forEach(function(node) { node.innerHTML = data; });
Dojo also provides a little shortcut for these kinds of things. You can specify a string to NodeList's forEach function like this:
// replace the contents of ALL <output> tags (as long as data is global)
dojo.query('output').forEach("item.innerHTML = data;");
The word item in the string is special. (This is a pain to debug, so it might not be worth it.)
As was said above, query method returns NodeList object, so you can iterate it's result as array, or use dojo methods that work with NodeList (e.g. attr):
dojo.query("#divOutput").attr("innerHTML", data);
But as soon as you are trying to query nodes by id, it would be better to use dojo.byId() method, which returns domNode:
dojo.byId("divOutput").innerHTML = data;
Or in more dojo style:
dojo.attr(dojo.byId("divOutput"), "innerHTML", data)
Try this by adding the [0] like this:
dojo.query("output")[0].innerHTML = data;
Also, there is a dojox.jq wrapper (in development, coming in 1.4) which emulates the JQuery return object APIs
The documentation seems to be a mess, this is the only thing i get to work with 1.7,
dojo.query("whatever").forEach(function(node, index, array)
{
node...
});