27

Is there a way in which I can test the content of the pseudo CSS class for :before on my element with Cypress?

I have seen links documenting:

But I have not found anything for CSS classes using the ::before pseudo class.

Imagine the code:

.myClass:before {
  content: "foo-";
}
<div>
  <span class="myClass">Bar</span>
</div>

How could one test that 'foo-' is present?

4 Answers 4

33

There's a way to assert on the CSS properties of pseudo-elements, although it's not as simple as just using a Cypress command.

  1. Use cy.get() to get a reference to the element.
  2. Read the Window object off of the element, and then invoke Window.getComputedStyle(), which can read the computed CSS of pseudo selectors.
  3. Use getPropertyValue on the returned CSS declaration to read the value of the content property.
  4. Assert on it.

Here's an example that works on the code posted in the OP:

cy.get('.myClass')
.then($els => {
  // get Window reference from element
  const win = $els[0].ownerDocument.defaultView
  // use getComputedStyle to read the pseudo selector
  const before = win.getComputedStyle($els[0], 'before')
  // read the value of the `content` CSS property
  const contentValue = before.getPropertyValue('content')
  // the returned value will have double quotes around it, but this is correct
  expect(contentValue).to.eq('"foo-"')
})
Sign up to request clarification or add additional context in comments.

1 Comment

I had the problem that it didn't work in Firefox. The solution seems to be to use :before instead of before, which also seems to work in chrome.
19

Based on Zach's answer I created a command that returns the pseudo-element property (without single quotes around).

function unquote(str) {
    return str.replace(/(^")|("$)/g, '');
}

Cypress.Commands.add(
    'before',
    {
        prevSubject: 'element',
    },
    (el, property) => {
        const win = el[0].ownerDocument.defaultView;
        const before = win.getComputedStyle(el[0], 'before');
        return unquote(before.getPropertyValue(property));
    },
);

You will use it like this

it('color is black', () => {
    cy.get('button')
       .before('color')
       .should('eq', 'rgb(0,0,0)'); // Or .then()
});

1 Comment

this seems pretty slick, but when I tried to implement it it gave me an error saying that "before" expected 2 arguments and only got one. The commands does show 2 arguments being passed (el & property), but it seems like the "prevSubject" should allow it to select the previously selected element in the cy.get. Any thoughts? Thanks!
0

Try asserting on the text of the parent:

cy.get('.myClass').parent().should('have.text', 'foo-bar')

If that doesn't work, you may have to use the textContent property:

cy.get('.myClass').parent(). should($el => expect ($el).to.contain('foo-bar')
)

1 Comment

Doesn't seem to work, both of these end up timing out on expected \n Bar\n to include foo-Bar
0

This was my solution to get, convert and compare a hexadecimal's background-color with a rgb returned.

const RGBToHex = (rgbColor) => {
  // it parse rgb(255, 13, 200) to #fa92D4
  const [red, green, blue] = rgbColor.replace(/[a-z]|\(|\)|\s/g, '').split(',');
  let r = parseInt(red, 10).toString(16);
  let g = parseInt(green, 10).toString(16);
  let b = parseInt(blue, 10).toString(16);

  if (r.length === 1) r = `0${r}`;
  if (g.length === 1) g = `0${g}`;
  if (b.length === 1) b = `0${b}`;

  return `#${r}${g}${b}`;
};


cy.get('.element').then(($el) => {
  const win = $el[0].ownerDocument.defaultView;
  const before = win.getComputedStyle($el[0], 'before');
  const bgColor = before.getPropertyValue('background-color');
  expect(RGBToHex(bgColor)).to.eq('#HEXA');
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.