XPATH and CSS for Selenium Automation - Help Required - css

I want to Find the XPATH/CSS locator to extract the text from the following structure.
Kindly help.
<div class="page-header song-wrap">
<div class="art solo-art">
<div class="meta-info">
<h1 class="page-title">
Zehnaseeb
I want to give the locator/XPATH so that it can return the text "Zehnaseeb" (In this case)
This did not yield any result,
driver.findElement(By.xpath(".//*[#id='main']/div/section/div[1]/div[2]/h1")).getText();

have you tried waiting for the element,
String text = new WebDriverWait(driver,30).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("div.page-header h1.page-title"))).getText();

If you are using C#, I recommend to use "ScrapySharp", it's very nice for parsing HTTML.
https://bitbucket.org/rflechner/scrapysharp/wiki/Home
Document htmlDoc = new HtmlDocument();
htmlDoc.loadHtml(driver.PageSource);
var zehnaseebstring = doc.DocumentNode.CssSelect("h1.page-title").SingleOrDefault().InnerText;
this should work.

I would check all the elements in between to see that the hierarchy is correct, but you could try to simplify by removing some of the elements in between by using descendant //
//*[#id='main']//h1[#class='page-title']

Related

Finding a path using CSS Selector in Selenium

I am trying to find an element using CSS Selector, using Selenium (Java).
This is my HTML.
<div class="PayMeth" widgetid="PayMeth_0" id="PayMeth_0">
<div class="Icon GIFT" data-dojo-attach-point="pmN"></div>
<div class="paytMethLab" data-dojo-attach-point="pmN">Program Card<br>
0000 000 0000 ****</div>
<div class="payMethAmtP" data-dojo-attach-point="pmAmtN">-$0.1</div>
</div>
I have used the following path but it is failing.
By.cssSelector("div[class=paytMethLab.contains(Program Card)]")
I want to get the text "Program Card".
Can someone please help. Thanks.
Here is the simple css that you can use.
div.paytMethLab
Here is the code
WebElement PayMeth = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("div.paytMethLab")));
String programcard= PayMeth .getText();
if(programcard.contains("Program Card"))
{
//your logic goes here.
}
This is what I used and it worked :)
WebElement PayMeth = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("div.paytMethLab")));
String programcard = PayMeth.getText();
if(programcard.contains("Program Card"))
{
// Do something
}

Html element which ignores all parent css

Im embeding a word document saved as html in my site, but there are conflicts between the generated css and my site’s. What could really help me is having a “scoped” element, which is not effecting or being effected by the site itself. Is there any solution to this problem? Thanks
I personally use classes as wrappers for scoping. Below all of the styles from the word document will be "scoped" to the beginning and ending of the span tag.
/*some css wrapper class*/
.word-document-wrapper
{
}
<span class="word-document-wrapper>
<!--word document here-->
</span>
You can use HtmlSaveOptions class to specify additional options when saving a Word document into the Html, Mhtml or Epub format. For example:
Document doc = new Document("D:\\Temp\\input.docx");
HtmlSaveOptions opts = new HtmlSaveOptions(SaveFormat.Html);
opts.CssStyleSheetType = CssStyleSheetType.Embedded;
opts.ExportImagesAsBase64 = true;
opts.ExportFontsAsBase64 = true;
opts.PrettyFormat = true;
doc.Save("D:\\temp\\18.8.html", opts);
I work with Aspose as Developer Evangelist.

Css selector for getting web element based on text

Below is the dom structure of the page :
I have tried
button:contains("srave")
I also tried
button[innerText="srave"]
button[text="srave"]`
button[innerHtml="srave"]`
none of them work.
Need way to get elements when element attribute is not defined.
PS: textContent() return srave as outcome.
Edit:
I have many such button elements on the page. I know I can iterate through all of them and check text. But I want to get web element directly based on the text it contains to reduce the execution time
Did you try: button[class='k-button k-button-icontext'] or button[dir='ltr'] I don't think the cssSelectors you were attempting in your example are correct because you pluralized button. If neither of these work, it may be that there are more than one button on the page with the same selector. In which case it might be better to use xpath or you could get a list of all the elements with the same selector and then get whichever one from that list you created and click it.
No, you can't use CSS Selector. You can use XPath.
//button[text()='srave']
Or
//button[contains(text(),'srave')]
You can use jquery for get the same because css is not select the text.
Working fiddle
fiddle link
Try this
alert($('button').find('span').html());
You can use following css to get the button name with "srave".
HTML
<button data-name="srave">
<span>Brave</span>
</button>
css
button[data-name="srave"] {
background:tomato;
}
To add to danidangerbear here is a java method that will do what you want:
public String getElementText(String elementText){
List<WebElement> elements = driver.findElements(By.cssSelector("button"));
String elementText = null;
for(WebElement element : elements)
if(element.getText().equals(actualValue)){
elementText = element.getText();
break;
} else {
elementText = "element text does not exist";
continue;
}
return elementText;
}

Nested elements naming style (Jade, HAML, Slim)

Looking for solution how to use SMACSS naming convention with jade, haml or slim template engine.
Expect following jade code :
.module
.child
.child
as output i'll get following:
<div class="module">
<div class="child"></div>
<div class="child"></div>
</div>
but i'd like to reach following result:
<div class="module">
<div class="module-child"></div>
<div class="module-child"></div>
</div>
is there any solution to manage it like i can do it in SASS for example, i mean avoid adding 'module-' string to each 'child' manually ?
UPDATE
Also acceptable solutions with Haml and Slim
This is the closest I got with jade (live playground here):
mixin e(elt)
- var a = attributes;
- var cl = attributes.class;delete attributes.class
- var elt = elt ? elt : 'div' // If no parameter given
if cl
- var cl = parent + '-' + cl
else
- var cl = parent
#{elt}&attributes({'class': cl}, attributes)
block
- var parent = 'box'
+e('aside')#so-special
+e('h2').title Related
+e('ul').list
+e('li').item: +e('a')(href='#').link Item 1
+e('li').item: +e('span').link.current Item 2 and current
+e('li').item#third(data-dash='fine', aria-live='polite') Item 3 not even a link
| multi-line
| block
// - var parent = 'other' problem of scope I guess
+e('li').item lorem ipsum dolor sit amet
- var parent = 'footer'
+e('footer')(role='contentInfo')
+e.inner © Company - 2014
A mixin named e will output an element taken as a parameter (default is div) with its attributes and content as is, except for the first class that'll be prefixed with the value of the variable parent (or will be the value of parent itself if it hasn't any class)
I prefer using default jade syntax for attributes, including class and id than passing many parameters to a mixin (this one doesn't need any if it's a div, as with .sth text'd output <div class="sth>text</div> and +e.sth text will output <div class="parent-sth>text</div>)
Mixin would be shorter if it didn't have to deal with other attributes (href, id, data-*, role, etc)
Remaining problem: changing the value of parent has no effect when it's indented. It had with simpler previous attempts so I guess it's related to scope of variables. You theoretically don't want to change the prefix for child elements but in practice... Maybe as a second optional parameter?
Things I had problem with while playing with jade:
attributes doesn't work as expected. Now it's &attributes(attributes). Thanks to jade-book issue on GitHub
but it'll output class untouched plus the prefixed one, so I had to remove it (delete) in a place it'd be executed by jade
Some thoughts from me: what's wrong with a variable?
- var myModule = 'module'
div(class="#{myModule}")
div(class="#{myModule}-child")
div(class="#{myModule}-child")
or combine it with an each:
- var myModule2 = 'foobar'
div(class="#{myModule2}")
each idx in [0, 1, 2, 3]
div(class="#{myModule2}-child") I'm child #{idx}
Sure, there is much more code to write, but if a change is neccessary then you must do this only at one point.
Ciao
Ralf
You should be able to achieve this with SASS. As long as you have the latest SASS version, you should be able to use the following syntax:
.module {
&-child {
}
}
Have a look at this article for more information on newer features of SASS http://davidwalsh.name/future-sass

How to apply CSS to second word in a string?

If I have the following string: John Smith, how could I use CSS to set font-weight: bold on the second word in order to achieve: John Smith.
Can this be done in pure CSS?
Update: I am retrieving user's name from the server, so in my template it is #{user.profile.name}.
Since a js solution was suggested and pure CSS isn't presently possible: Live demo (click).
Sample markup:
<p class="bold-second-word">John Smith</p>
<p class="bold-second-word">This guy and stuff.</p>
JavaScript:
var toBold = document.getElementsByClassName('bold-second-word');
for (var i=0; i<toBold.length; ++i) {
boldSecondWord(toBold[i]);
}
function boldSecondWord(elem) {
elem.innerHTML = elem.textContent.replace(/\w+ (\w+)/, function(s, c) {
return s.replace(c, '<b>'+c+'</b>');
});
}
It cannot be done in pure CSS, sorry. But if you are willing to accept a JavaScript fix, then you might want to look into something like this:
Find the start and end index of the second word in the element's textContent.
Add contenteditable attribute to element.
Use the Selection API to select that range.
Use execCommand with the bold command.
Remove contenteditable attribute.
EDIT: (just saw your edit) I agree this is a bit too hack-y for most uses. Perhaps you'd be better off saving what the last name is as meta-data?
It seems to be impossible by using only pure CSS. However, with a bit of JS you could get there pretty easily:
const phrases = document.querySelectorAll('.bold-second-word');
for (const phrase of phrases) {
const words = phrase.innerHTML.split(' ');
words[1] = `<b>${words[1]}</b>`; // this would return the second word
phrase.innerHTML = words.join(' ');
}
<p class="bold-second-word">John Smith</p>
<p class="bold-second-word">Aaron Kelly Jones</p>

Resources