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

Incorrect behaviour when statically rendering components returning strings #2098

Closed
2 of 13 tasks
ottosichert opened this issue Apr 13, 2019 · 4 comments · Fixed by #2221
Closed
2 of 13 tasks

Incorrect behaviour when statically rendering components returning strings #2098

ottosichert opened this issue Apr 13, 2019 · 4 comments · Fixed by #2221

Comments

@ottosichert
Copy link
Contributor

Current behavior

Using Enzyme's static render() on a component that returns a string returns an empty result or breaks:

Setup

import chai from "chai";
import chaiEnzyme from "chai-enzyme";
import Enzyme from "enzyme";
import Adapter from "enzyme-adapter-react-16";

Enzyme.configure({ adapter: new Adapter() });
chai.use(chaiEnzyme());

Tests

import { expect } from "chai";
import { render } from "enzyme";
import React from "react";

const Identity = props => props.children;

describe("Components rendering a string", () => {
  it("should contain this string", () => {
    const wrapper = render(<Identity>foo</Identity>);
    expect(wrapper.text()).to.equal("foo");
  });

  it("should not break static rendering", () => {
    const wrapper = render(<Identity>bar!</Identity>);
    expect(wrapper.text()).to.equal("bar!");
  });

  it("should work as expected when wrapping in a DOM element", () => {
    const wrapper = render(
      <div>
        <Identity>foo</Identity>
      </div>
    );
    expect(wrapper.text()).to.equal("foo");
  });
});

Results

  Components rendering a string
    1) should contain this string
    2) should not break static rendering
    ✓ should work as expected when wrapping in a DOM element

  1 passing (329ms)
  2 failing

  1) Components rendering a string
       should contain this string:

      AssertionError: expected '' to equal 'foo'
      + expected - actual

      +foo

      at Context.equal (test.js:10:31)

  2) Components rendering a string
       should not break static rendering:
     SyntaxError: Unmatched selector: !
      at parse (node_modules/css-what/index.js:85:9)
      at compileUnsafe (node_modules/css-select/lib/compile.js:31:14)
      at select (node_modules/css-select/index.js:18:49)
      at CSSselect (node_modules/css-select/index.js:41:9)
      at initialize.exports.find (node_modules/cheerio/lib/api/traversing.js:40:21)
      at initialize.module.exports (node_modules/cheerio/lib/cheerio.js:88:18)
      at new initialize (node_modules/cheerio/lib/static.js:34:20)
      at initialize (node_modules/cheerio/lib/static.js:31:14)
      at render (node_modules/enzyme/build/render.js:42:39)
      at Context.<anonymous> (test.js:14:21)

The results are identical when using class components.

Expected behavior

All tests should pass

Your environment

API

  • shallow
  • mount
  • render

Version

library version
enzyme 3.8.0
react 16.7.0
react-dom 16.7.0
react-test-renderer 16.7.0
adapter (below) 1.7.1
cheerio 1.0.0-rc.2
chai 4.2.0
chai-enzyme 1.0.0-beta.1

Adapter

  • enzyme-adapter-react-16
  • enzyme-adapter-react-16.3
  • enzyme-adapter-react-16.2
  • enzyme-adapter-react-16.1
  • enzyme-adapter-react-15
  • enzyme-adapter-react-15.4
  • enzyme-adapter-react-14
  • enzyme-adapter-react-13
  • enzyme-adapter-react-helper
  • others ( )
@ljharb
Copy link
Member

ljharb commented Apr 14, 2019

What is wrapper.debug() for those first two test cases?

@ottosichert
Copy link
Contributor Author

Both wrappers are Cheerio instances, and for the second test should not break static rendering the creation of the wrapper fails. That means there is no wrapper.debug() in both cases.

The offending lines seem to be this:

https://github.com/airbnb/enzyme/blob/0a1740470ddc7b69d7676d50bd2d8fdc291eb921/packages/enzyme/src/render.js#L21-L22

Reproducing this manually in node v8.15.1 gives some insights:

> const cheerio = require("cheerio");
undefined
> let html = "foo";
undefined
> let wrapper = cheerio.load("")(html); // Test "should contain this string"
undefined
> wrapper
initialize {
  options:
   { withDomLvl1: true,
     normalizeWhitespace: false,
     xml: false,
     decodeEntities: true },
  _root:
   initialize {
     '0':
      { type: 'root',
        name: 'root',
        namespace: 'http://www.w3.org/1999/xhtml',
        attribs: {},
        'x-attribsNamespace': {},
        'x-attribsPrefix': {},
        children: [Array],
        parent: null,
        prev: null,
        next: null },
     options:
      { withDomLvl1: true,
        normalizeWhitespace: false,
        xml: false,
        decodeEntities: true },
     length: 1,
     _root: [Circular] },
  length: 0,
  prevObject:
   initialize {
     '0':
      { type: 'root',
        name: 'root',
        namespace: 'http://www.w3.org/1999/xhtml',
        attribs: {},
        'x-attribsNamespace': {},
        'x-attribsPrefix': {},
        children: [Array],
        parent: null,
        prev: null,
        next: null },
     options:
      { withDomLvl1: true,
        normalizeWhitespace: false,
        xml: false,
        decodeEntities: true },
     length: 1,
     _root: [Circular] } }
> html = "bar!";
'bar!'
> wrapper = cheerio.load("")(html); // Test "should not break static rendering"
SyntaxError: Unmatched selector: !

Passing html to cheerio.load() directly gives the correct results in this case when there is no wrapping DOM element:

> const cheerio = require("cheerio");
undefined
> const html = "bar!";
'bar!'
> const wrapper = cheerio.load(html);
{ [Function: initialize]
  fn:
   initialize {
     constructor: [Circular],
     _originalRoot:
      { type: 'root',
        name: 'root',
        namespace: 'http://www.w3.org/1999/xhtml',
        attribs: {},
        'x-attribsNamespace': {},
        'x-attribsPrefix': {},
        children: [Array],
        parent: null,
        prev: null,
        next: null } },
  load: [Function],
  html: [Function],
  xml: [Function],
  text: [Function],
  parseHTML: [Function],
  root: [Function],
  contains: [Function],
  merge: [Function],
  _root:
   { type: 'root',
     name: 'root',
     namespace: 'http://www.w3.org/1999/xhtml',
     attribs: {},
     'x-attribsNamespace': {},
     'x-attribsPrefix': {},
     children: [ [Object] ],
     parent: null,
     prev: null,
     next: null },
  _options:
   { withDomLvl1: true,
     normalizeWhitespace: false,
     xml: false,
     decodeEntities: true } }
> wrapper.text()
'bar!'

@ljharb
Copy link
Member

ljharb commented Apr 14, 2019

Hmm - this seems related to the breaking changes made to adapt to Cheerio v1 in enzyme 3.

@ottosichert
Copy link
Contributor Author

For reference:

ottosichert added a commit to ottosichert/enzyme that referenced this issue Aug 11, 2019
- Fix enzymejs#2098
- Introduce `loadCheerioRoot` util
- Use util in `render`, `mount` and `shallow`
ottosichert added a commit to ottosichert/enzyme that referenced this issue Sep 16, 2019
- Fix enzymejs#2098
- Introduce `loadCheerioRoot` util
- Use util in `render`, `mount` and `shallow`
ottosichert added a commit to ottosichert/enzyme that referenced this issue Sep 16, 2019
- Fix enzymejs#2098
- Introduce `loadCheerioRoot` util
- Use util in `render`, `mount` and `shallow`
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 16, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 16, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ottosichert added a commit to ottosichert/enzyme that referenced this issue Sep 16, 2019
- Fix enzymejs#2098
- Introduce `loadCheerioRoot` util
- Use util in `render`, `mount` and `shallow`
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 16, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ottosichert added a commit to ottosichert/enzyme that referenced this issue Sep 16, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 17, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 17, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 18, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 18, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 18, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 18, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 18, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 19, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 19, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 19, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 19, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 23, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 23, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 23, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 23, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
ljharb pushed a commit to ottosichert/enzyme that referenced this issue Sep 23, 2019
 - [enzyme] [fix] `render`: handle Fiber strings and numbers
 - [enzyme] [new] `Utils`: add `loadCheerioRoot`

Fixes enzymejs#2098
@ljharb ljharb closed this as completed in d9cc09e Sep 23, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants