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

Unable to get text() from a string wrapped with curly braces #1514

Closed
2 of 10 tasks
DaveStein opened this issue Feb 5, 2018 · 9 comments
Closed
2 of 10 tasks

Unable to get text() from a string wrapped with curly braces #1514

DaveStein opened this issue Feb 5, 2018 · 9 comments

Comments

@DaveStein
Copy link

DaveStein commented Feb 5, 2018

Current behavior

I have a couple of lines like this in my test:

const app = shallow(<App {...state} />);
expect(app.find('#store').text()).toEqual(JSON.stringify(state));

The markup is this: <script type="text/html" id="store" dangerouslySetInnerHTML={{__html: JSON.stringify(this.props)}}></script>.

I believe it's failing because it translates to a string with curly braces. For example, .text() will return...

  • "Hello" from <script type="text/html" id="store">Hello</script>
  • ""from <script type="text/html" id="store">{}</script>

Expected behavior

A way to get the contents, even if they are JSON/JS.

Your environment

API

  • shallow
  • mount
  • render

Version

library version
Enzyme ^3.3.0
React ^16.2

Adapter

  • enzyme-adapter-react-16
  • enzyme-adapter-react-15
  • enzyme-adapter-react-15.4
  • enzyme-adapter-react-14
  • enzyme-adapter-react-13
  • enzyme-adapter-react-helper
  • others ( )
@karak
Copy link

karak commented Feb 9, 2018

mount(), rather than shallow(), provides what you want.

Shallow-renderer doesn't render the internal components.

Or, dive() also would help you in general cases,
but didn't in this case (I don't know why, sorry).

Try the following codes:

it('test deep node', () => {
    function Script(props) {
        return <span>{props.text}</span>;
    }

    function App(props) {
        return (
            <div>
                <Script type="text/html" id="store" text={JSON.stringify(props)}></Script>
            </div>
        );
    }
    
    const state = { "hello": "HELLO" };
    
    expect(mount(<App {...state} />).find('#store').text()).toEqual(JSON.stringify(state));
    
    expect(shallow(<App {...state} />).find('#store').dive().text()).toEqual(JSON.stringify(state));

});

EDIT:
I wonder why this is tagged as "bug"? @ljharb
For I have sometimes avoided shallow since I had met a similar issue.

@DaveStein
Copy link
Author

This is not an issue with shallow. As I indicated above I tried markup that does not use any prop values, aside from what I really wanted with the innerHTML. The string Hello returns fine. The string {} does not. I also wouldn't think that a regular HTML node like script would count as a subcomponent that wouldn't get rendered with shallow. I had also tried using render with same effect.

@karak
Copy link

karak commented Feb 10, 2018

@DaveStein
Oh, I confused with our past issues I remember.

However, HTML with no {} still returns empty as long as I tested,
and mount successes, while shallow and render fail.

Here's my test code:

function App(props) {
    return (
        <div>
            <script type="text/html" id="store" dangerouslySetInnerHTML={{__html: "HELLO"}}></script>
        </div>
    );
}

it('test render', () => {
    expect(render(<App />).find('#store').text()).not.toBe(''); // NG
});

it('test mount', () => {
    expect(mount(<App />).find('#store').text()).not.toBe(''); // OK
});

it('test shallow', () => {
    expect(shallow(<App />).find('#store').text()).not.toBe(''); // NG
});

@ljharb
Copy link
Member

ljharb commented Feb 20, 2018

This is a good point; .text() reads out the children property, but in shallow in particular, it's probably not reading from dangerouslySetInnerHTML.

Separately, it's possible that render has a bug with dangerouslySetInnerHTML.

@DaveStein
Copy link
Author

@karak in your example, did you meant to set {} as your innerHTML? Cause I believe HELLO prints fine in all cases.

@karak
Copy link

karak commented Feb 20, 2018

@DaveStein No, just set "HELLO" and got empty in some cases, as far as I tested, on react 16.2.0 and enzyme 3.3.0.

@ljharb render did success when replacing <script> by <div>. It seems to have some special behavior for <script>.

ADD:
The API in Cheerio says render excludes script as well as comment and style at https://github.com/cheeriojs/cheerio/blob/master/lib/static.js#L111.
I think it's inappropriate because textContent should include them while innerText not according to MDN, but they does it.

@karak
Copy link

karak commented Feb 21, 2018

@ljharb I found Cheerio 1.0.0-rc.2, depended by Enzyme 3.3.0, is going to have a breaking change by cheeriojs/cheerio#1050. Is the dependency considered to be valid?

@ljharb
Copy link
Member

ljharb commented Feb 23, 2018

render will do whatever cheerio does.

ljharb added a commit that referenced this issue Jul 7, 2018
@ljharb
Copy link
Member

ljharb commented Jul 7, 2018

So, I think the underlying issue here is that shallow doesn't currently support dangerouslySetInnerHTML.

I'm going to close this in favor of #1297 / #419.

@ljharb ljharb closed this as completed Jul 7, 2018
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