0

In my HTML I have element such as below

HTML:

<hmtl>
    <head>
        <style>
            label::after {
            content: " *"
            }
        </style>
    </head>
    <body>
        <label> I'm mandatory</label>
    </body>
</hmtl>

So what gets displayed on browser is:

I'm mandatory *

Query Selector

>getComputedStyle(document.querySelector('label')).content
<"normal"

So I see normal instead of *.

I can't see where is normal coming from. Is this the correct way to test content of ::after CSS selector?

I want to test that there's a "*" after the label, but can't seem to be able to get the value of "content" property correctly. Once I'm able to find it in using browser DOM API, I'd eventually want to test it in protractor.

Update

I found the answer at - Selenium WebDriver get text from CSS property "content" on a ::before pseudo element. Now the question remains how I would test this on protractor.

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
Phalgun
  • 1,181
  • 2
  • 15
  • 42
  • from where word `normal`? Could it be that you get wrong element? – Oleksii Feb 05 '19 at 20:43
  • I've added a small HTML snippet and also the result of querySelector(). The label element is being correctly selected, but I guess there's some work remaining to get the proper value for ::after – Phalgun Feb 06 '19 at 03:52

3 Answers3

2

Window.getComputedStyle()

The Window.getComputedStyle() method returns an object containing the values of all CSS properties of an element, after applying active stylesheets and resolving any basic computation those values may contain. Individual CSS property values are accessed through APIs provided by the object, or by indexing with CSS property names.

  • Syntax:

    var style = window.getComputedStyle(element [, pseudoElt]);
    
    element
        The Element for which to get the computed style.
    pseudoElt (Optional)
        A string specifying the pseudo-element to match. Omitted (or null) for real elements.
    
    The returned style is a live CSSStyleDeclaration object, which updates automatically when the element's styles are changed.
    
  • You can find a related discussion in WebDriver select element that has ::before


Usage with pseudo-elements

getComputedStyle() can pull style info from pseudo-elements (such as ::after, ::before, ::marker, ::line-marker.

As per the HTML, the <style> is as follows:

<style>
    label::after {
    content: " *"
    }
</style>

Implemented as:

<label> I'm mandatory</label>

To retrieve you need to:

var label = document.querySelector('label'); 
var result = getComputedStyle(label, ':after').content;

console.log('the generated content is: ', result); // returns ' *'

Reference

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
1

const label = document.querySelector('label'); // "normal";

console.log(label);


const labelAfter = getComputedStyle(label, ':after').content;

console.log(labelAfter == "normal");
label::after {
  content: " *"
}
<label> I'm mandatory</label>
Air
  • 181
  • 3
  • 15
0

Since my question was specifically w.r.t protractor I'm posting the solution that I got working. Coming to the part I was stuck initially - why do I get "normal" instead of " *"

>getComputedStyle(document.querySelector('label')).content
<"normal"

So earlier I was unaware that ::after creates a pseudo child element inside the label element.

Inspecting <label> element in Chrome shows the below HTML

<label>
    I'm mandatory
    ::after
</label>

If I click<label> element and checked the Computed tab, I could see that the value for content property is normal.

However, if I click on ::after pseudo-element, I can see in the Computed tab the value for content property is " *".

As mentioned in the other answers getComputedStyle() with the pseudo element as second parameter, is the only way to get value of CSS property for "::after". The crux of the problem is that protractor does not have an equivalent for getComputedStyle(), so we have to rely upon browser.executeScript() as shown below:

let labelHeader = 'I'm mandatory *';
// Passing label element separately as in the real test case, it would be extracted from parent
// enclosing element and need to be able to pass it as a parameter to browser.executeScript().

let label = element(by.css('label'));
browser.executeScript("return window.getComputedStyle(arguments[0], ':after').content",
                       label)
    .then ((suffixData: string) => {
     // suffixData comes out to be '" *"', double quotes as part of the string.
     // So get rid of the first and last double quote character

         suffixData = suffixData.slice(1, suffixData.length - 1);
         labelText += suffixData;
         expect(labelText).toBe(labelHeader);
     });
Phalgun
  • 1,181
  • 2
  • 15
  • 42