Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing content of dangerouslySetInnerHTML. enzyme v3 (passed in v2) #1297

Closed
peter-mouland opened this issue Oct 24, 2017 · 11 comments
Closed

Comments

@peter-mouland
Copy link
Contributor

peter-mouland commented Oct 24, 2017

Within v2, i could set the contents of a component using dangerouslySetInnerHTML.
Enzyme could then test this contents using the .find method and the prop(s).

Within v3, the content of dangerouslySetInnerHTML is not found.

Is this something that is no longer supported or a regression? (Thinking about, it i'm surprised it ever worked!)

Or, is there an example to how to test this?

Thanks for your time.

Example component:

// svg.js
import React from 'react'

export default ({ height, width, children, className, symbol = false, id, use, ...props }) => {
  const isBase64 = typeof children === 'string' && children.indexOf('data') === 0
  let svg = use ? `<svg ><use xlink:href='#${use}' /></svg>` : children
  if (id) svg = svg.replace(/(<svg[^>]*) id=".*?"/ig, '$1').replace('<svg', `<svg id="${id}"`)
  if (height) svg = svg.replace(/(<svg[^>]*) height=".*?"/ig, '$1').replace('<svg', `<svg height="${height}"`)
  if (width) svg = svg.replace(/(<svg[^>]*) width=".*?"/ig, '$1').replace('<svg', `<svg width="${width}"`)
  if (symbol) svg = svg.replace('<svg', '<svg style="display: none;" ><symbol')
  return isBase64
    ? <img src={svg} className={className} {...props} />
    : <span dangerouslySetInnerHTML={{ __html: svg }} className={className} {...props} />
}

Test Passes in v2, fails in v3

// svg.spec.js


import React from 'react'
import { shallow, render } from 'enzyme'
import Chance from 'chance'

import Svg from './Svg'

const chance = new Chance()
const svg = '<svg class="test-svg" xmlns="http://www.w3.org/2000/svg" />'
const defaultMockProps = {
  id: chance.word()
}

describe('Svg', () => {
  it('renders the use href using xlink (needed for safari)', () => {
    const component = render(<Svg use={defaultMockProps.id} />)
    const use = component.find('use')
    expect(use.prop('xlink:href')).toBe(`#${defaultMockProps.id}`)
  })
})

edit: removed re-written test which was going off topic and moved to another issue

@ljharb
Copy link
Member

ljharb commented Oct 25, 2017

I would expect dangerouslySetInnerHTML to work in v3.

@peter-mouland
Copy link
Contributor Author

peter-mouland commented Oct 25, 2017

The component.find('use') returns a length of 0, so i've re-written as:

  it('renders the use href using xlink (needed for safari)', () => {
    const component = shallow(<Svg use={defaultMockProps.id} />)
    expect(component.html()).toContain(`xlink:href='#${defaultMockProps.id}'`)
  })

I think this is fine, and an understandable rewrite (since the component essentially just writes innerHTML).

@ljharb
Copy link
Member

ljharb commented Oct 25, 2017

@aweary could this be an issue with rst-selector-parser? (the .find('use') not working)

@exitudio
Copy link
Contributor

exitudio commented Nov 1, 2017

cheerio (which render() function is using under the hood) automatically convert xlink:href to href.

I tried to render {__html: "<svg ><use xlink:href='#1' /></svg>"}
and get prop by use.prop('href') is working.

Maybe, it's not a bug?

@ljharb
Copy link
Member

ljharb commented Nov 1, 2017

@exitudio that seems like a bug worth filing on cheerio

@peter-mouland
Copy link
Contributor Author

peter-mouland commented Nov 1, 2017

I think I know why cheerio might have done this, I remember reading that <use xlink:href is deprecated and <use href is preferred... but since safari only supports the deprecated syntax (as shown in this codepen demo) it feels like it's premature to have removed support. It may have been intentional to remove xlink, but i think support should be added.

In my case i've added a test to ensure xlink exists otherwise someone else might remove it and not test the outcome in safari (as I almost did while refactoring!).

I guess the question becomes, if i add an attribute foo:bar='baz', how should we expect to find it in enzyme? As explained in my use case, the foo part is important and the test would be invalid if i excluded it from the selector.

To clarify
i've retested, and as @exitudio alluded too: render does find use, but fails at the .prop('xlink:href'). However, in Enzyme v2 - it would also be able to find .prop('xlink:href')

@peter-mouland
Copy link
Contributor Author

peter-mouland commented Nov 1, 2017

I was going to suggest taking guidance from the DOM. I get mixed results, but i I would probably expect .prop to function as .getAttribute (while .find is similar to .querySelector), in which case it could be argued the behaviour of v2 was correct.

  • $0.getAttribute('foo:bar') returns 'baz'
  • $0.getAttribute('bar') return null
  • document.querySelector('svg[xlink:href]') returns VM232:1 Uncaught DOMException
  • document.querySelector('svg[href]') returns null

@exitudio
Copy link
Contributor

exitudio commented Nov 2, 2017

enzyme v2 is using cheerio@^0.22.0
enzyme v3 is using cheerio@^1.0.0-rc.2

This code works with cheerio@^0.22.0

cheerio.load('')('<span><svg ><use xlink:href="#1" /></svg></span>').find('use').prop('xlink:href')

So the point is we should stick on cheerio@^0.22.0?

@ljharb
Copy link
Member

ljharb commented Nov 2, 2017

No, but an issue should be filed on cheerio so that v1 can adjust to this behavior.

@ljharb
Copy link
Member

ljharb commented Dec 22, 2020

@exitudio can you update to cheerio's latest release, and try again?

@ljharb
Copy link
Member

ljharb commented Dec 22, 2020

I've confirmed that the latest cheerio release fixes it; I'll close this with a passing test case.

@ljharb ljharb closed this as completed in 95f8c40 Dec 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants