0

I need to select any child element of SVG component, it can be rect, text, defs etc.

I am trying it with playwright. I tried this

const elementsCount = await page.locator("//*[local-name()='svg']").count()
console.log("Elements count = " + elementsCount)

and I get elementsCount 0. Same result when I replace local-name with name.

In Cypress I am trying something as

cy.get('svg', { timeout: 10000 }).find('text').eq(0).click()

However I get error:

Expected to find element: svg,but never found it. 

I attached screenshot with DOM. Any advice how to select children of SVG? I am wondering does line "#document# before SVG tag have impact on the query?

enter image description here

0

1 Answer 1

1

The <object> element is blocking access to the svg, which appears to be read in from the API and displayed via some code internal to the <object> element (perhaps it is a web component).

The only way I can see to query the <svg> and it's children is to intercept the API call and append it to the document under test at the bottom.

This may disrupt the click actions of the page, but you would be able to query the <svg> as a static piece of HTML.

Something like this:

 
cy.get('object').eq(39)      // first get the parent object
  .invoke('attr', 'data')    // extract the data attribute
  .then(dataLoc => {

    // make a request to the API
    cy.request(`https://demo.netbox.dev${dataLoc}`)
      .then(response => {

        // convert the XML response to HTML
        const parser = new DOMParser();
        const doc = parser.parseFromString(response.body, "application/xml");
        const svg = doc.children.item(0)

        // put the HTML in a container and add it to the page         
        const div = document.createElement('div')
        div.id = 'svgContainer'
        div.appendChild(svg)
        cy.get('body').then($body => {
          $body[0].appendChild(div)
        })

        // now we can query the SVG without the parent object interfering
        cy.get('#svgContainer').within(() => {
          cy.get('svg').find('text').eq(0)
          .then($text => {
            Cypress.log({
              name: 'svg > text', 
              message: $text.text()
            })
          })
        })
      })
  })
Sign up to request clarification or add additional context in comments.

3 Comments

It works, thanks a lot. Now I can read text. However, there are <a> tags bellow the '<text' tags and I need to click on it. However, it is not clickable. I tried to do this: cy.get('#svgContainer').within(() => { cy.get('svg').find('a').eq(10).as('cell') }) cy.get('@cell').should('have.text', 'add device').click({ force: true })
This approach is limited - the svg you are querying is a different instance to the one on the page so you're not really interacting with the page any more.
If the <object> is a web component as I suspect, it is very difficult to test with DOM based frameworks like Cypress & Playwright. If you have access to the source code, a component-testing approach might work better.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.