Search code examples
playwrightplaywright-python

Cannot get class name from node after locating it in playwright


I have an SVG object like that:

<svg class="class-a color-green marker" .../>

In Playwright I want to get an exact list of classes of this element. I use the following code to locate it:

page.locator(".status-marker").first

The node is located properly, but when I call evaluate("node => node.className") on it, I get an empty dict, like the locator stripped all information about classes at all.

In general, it doesn't matter how I get the handle of this element, I always get an empty dict on evaluate("node => node.className").

Calling page.locator(".status-marker").first.is_visible() returns True, so the object exists.

Also if I run page.locator(".status-marker").first.evaluate("node => node.outerHTML") I'll get the full HTML of that node, that does have the class name included. I could parse that, but it would be pretty clunky solution.

I found out that I could use expect(locator).to_have_class(), but If the node has more than one class I need to put all of them for it to pass, when I care only on one of them (the other classes are dynamically generated, so I can't even know about them during tests).

Edit:

Here's some additional sample:

assert page.locator(".marker").first.evaluate("node => node.className") == {}
expect(page.locator(".marker").first).to_have_class("text-green-1")

The first assert passes - the evaluate("node => node.className") returns an empty dict. The expect() fails with the following error:

AssertionError: Locator expected to have class 'text-green-1'
E       Actual value: inline pr-2 text-green-1 marker svelte-fa s-z-WEjw8Gh1FG

I've found a way to reproduce it (it happens to me in font awesome plugin for svelte):

def test_svelte_fa(page):
    page.goto("https://cweili.github.io/svelte-fa/")

    item = page.locator(".svelte-fa").first
    assert item.is_visible()
    assert "svelte-fa" in item.evaluate("node => node.className")

Solution

  • In your example, the className of an SVG is an SVGAnimatedString object. Which is not serializable.
    If you do JSON.stringify($('.svelte-fa').className) on the browser, you will see that the value is {}.
    Values returned by the evaluate function needs to be serializable.