Enzyme: How do I get the correct width of my component?

Created on 12 Feb 2018  路  16Comments  路  Source: enzymejs/enzyme

I have a customized component which encapsulates a react-table in it. And I want to unit-test this component.
I use jsdom to generate the window and document. Then I use mount to begin with the unit test.
In my component, there is a function to set all the columns' width calculated based on the react-table's width.
I found several things weird:

  1. The document.getElementById always return null;
  2. The react-table's width is 0;
  3. expect(wrapper.find('.rt-tr-group').length).toBeGreaterThan(0); this assert is true(which means the table has data and rendered all the rows) while the react-table shows no data text in the output of the document.documentElement.outterHTML;

Current behavior

The react-table's width is 0.

Expected behavior

The react-table's width should be the same as the container's width.

Your environment

API

  • [ ] shallow
  • [x] mount
  • [ ] render

Version

"enzyme": "^3.2.0",
"jsdom": "^11.5.1",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-table": "^6.5.1",

Adapter

  • [ ] enzyme-adapter-react-16
  • [x] enzyme-adapter-react-15
  • [ ] enzyme-adapter-react-15.4
  • [ ] enzyme-adapter-react-14
  • [ ] enzyme-adapter-react-13
  • [ ] enzyme-adapter-react-helper
  • [ ] others ( )

below are the snippets of my code:
code in the setup file for jest:
const jsdom = new JSDOM('<!doctype html><html><body></body></html>', { pretendToBeVisual: true });const { window } = jsdom;

code in the spec file:
const wrapper = mount( <DataViewTable data={global.productsList} idKey="uuid" initSelectedItems={[]} onSelectChange={mockProps.onSelectChange} onRowClicked={(info) => { mockProps.onRowClicked(info); }} initialSort={[{ id: 'lastEdit', desc: true }]} columns={mockColumns} getComponentDOM={mockProps.getTableDOM} noDataText={'mock no data text'} sortByColumn={(id, desc) => { mockProps.sortByColumn(id, desc); }} />);

Most helpful comment

@mklimek I got it. mount render a Component to a DOM node which is created by document.createElement('div').

https://github.com/airbnb/enzyme/blob/master/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js#L163

It means that the component isn't attached a DOM tree so the height is always 0.
If you want to attach the component to the DOM tree, you can use attachTo option.

https://github.com/airbnb/enzyme/blob/master/docs/api/ReactWrapper/detach.md

When you use attachTo option, you should detach the DOM node.

All 16 comments

I have pretty similar problem with a pretty simple component.
I try to get clientWidth using ref but it always returns 0.
I use Karma with Chrome for testing.

Could you create a repository to reproduce this?

@koba04
I created the rep, and here is the link:
https://github.com/hex-fire/Sample-1525.git

I set the width of the react table and its direct parent to 100% and set the width of the root div to 1024px,
but it still prints out 0.

@koba04 just check console log for this kind of snippet:

render() {
    return (
        <div ref="div-ref">
            Test div
        </div>
    )
}

componentDidUpdate () {
    const obj = this.refs['div-ref']
    const height = obj.clientHeight
    console.log(height)
}

This issue might not be relevant to enzyme because the following script also prints 0.

document.body.innerHTML = '<div id="hoge">foo</div>';
console.log(document.querySelector('#hoge').clientHeight);

@koba04 how did you test it?
A snippet you posted (and mine too) works perfectly.

https://jsfiddle.net/65m79L9p/1/

@mklimek I tested it on https://github.com/hex-fire/Sample-1525.git ,which is based on Jest(jsdom).

I wouldn't be surprised if jsdom is not capable to measure its content by design.
However, in my case, where Chrome is an environment, it should work ok.
Shouldn't it?

@mklimek I got it. mount render a Component to a DOM node which is created by document.createElement('div').

https://github.com/airbnb/enzyme/blob/master/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js#L163

It means that the component isn't attached a DOM tree so the height is always 0.
If you want to attach the component to the DOM tree, you can use attachTo option.

https://github.com/airbnb/enzyme/blob/master/docs/api/ReactWrapper/detach.md

When you use attachTo option, you should detach the DOM node.

@koba04 it works with attachTo .

document.body.innerHTML = '<div id="hoge"></div>';
const options = {
    attachTo: document.querySelector('#hoge')
}
const sut = mount(<ImagesGrid />, options)

Thanks for your help!

This seems answered.

@mklimek
Can provide a complete demo? The clientHeight I obtained is still 0.
And, when I use jsdom, I can't get the elements I want to test.

I have a similar issue.
With this test:

describe('outerHeight', () => {
  beforeAll(() => {
    document.body.innerHTML = `<div id="test" 
        style="display: inline-block; width: 200px; height: 150px; margin: 10px;"></div>`;
  });

  test('xxx', () => {
    const elem = document.getElementById(elemId);
    const { offsetHeight, clientHeight } = elem;
  });
});

Both offsetHeight and clientHeight are 0, but if I try to get the height with the margins I get 20px:

let height = elem.offsetHeight;
const style = getComputedStyle(elem);
height += parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10);

I have a similar issue. it dosen't work https://github.com/airbnb/enzyme/issues/1940

does attachTo suppose to work with shallow ?

No, attachTo only works with mount.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aweary picture aweary  路  3Comments

nelsonchen90 picture nelsonchen90  路  3Comments

ivanbtrujillo picture ivanbtrujillo  路  3Comments

blainekasten picture blainekasten  路  3Comments

thurt picture thurt  路  3Comments