storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
84.67k stars 9.32k forks source link

react-beautiful-dnd outputs "Droppable has not been provided with a ref." in storyshots #3556

Closed ttoohey closed 6 years ago

ttoohey commented 6 years ago

Bug or support request summary

Storyshots with https://github.com/atlassian/react-beautiful-dnd output an error message:

    console.error node_modules/react-beautiful-dnd/dist/react-beautiful-dnd.cjs.js:4694

              Droppable has not been provided with a ref.
              Please use the DroppableProvided > innerRef function

I'm expecting the fix will require "mocking refs" but am looking for some guidance on how to do that. I've looked through https://github.com/storybooks/storybook/issues/1820 but I'm still not clear what should be done.

Steps to reproduce

From a create-react-app based project with storybook initialised using getstorybook. The following code is from react-beautiful-dnd's readme examples

// stories/index.js
import React from 'react';
import { storiesOf } from '@storybook/react';
import { DragDropContext, Droppable } from 'react-beautiful-dnd';

storiesOf('react-beautiful-dnd', module)
  .add('Droppable', () => (
    <DragDropContext>
      <Droppable droppableId="droppable-1" type="PERSON">
        {(provided, snapshot) => (
          <div
            ref={provided.innerRef}
            {...provided.droppableProps}
          >
            <h2>I am a droppable!</h2>
            {provided.placeholder}
          </div>
        )}
      </Droppable>
    </DragDropContext>
  ))
// stories/storyshots.test.js
import initStoryshots from '@storybook/addon-storyshots';
initStoryshots();
npm test -- -t storyshots

Please specify which version of Storybook and optionally any affected addons that you're running

Hypnosphi commented 6 years ago

You can try something like this:

import initStoryshots, { snapshotWithOptions } from '@storybook/addon-storyshots'

initStoryshots({
  test: snapshotWithOptions({
    createNodeMock: (element) => {
      if (typeof element.type === 'string') {
        return document.createElement(element.type)
      }
    },
  }),
})
ttoohey commented 6 years ago

@Hypnosphi - thanks for that, that seems to work for the simple example.

I've now tried with the Draggable component from react-beautiful-dnd and it has another problem that seems related, but I'm stuck again trying to understand what it means.

// stories/index.js
import React from 'react';
import { storiesOf } from '@storybook/react';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';

storiesOf('react-beautiful-dnd', module)
  .add('Draggable', () => (
    <DragDropContext>
      <Droppable droppableId="droppable-1" type="PERSON">
        {(provided, snapshot) => (
          <div
            ref={provided.innerRef}
            {...provided.droppableProps}
          >
            <Draggable draggableId="draggable-1" index={0}>
              {(provided, snapshot) => (
                <div
                  ref={provided.innerRef}
                  {...provided.draggableProps}
                  {...provided.dragHandleProps}
                >
                  <h4>My draggable</h4>
                </div>
              )}
            </Draggable>
            {provided.placeholder}
          </div>
        )}
      </Droppable>
    </DragDropContext>
  ))
// stories/storyshots.test.js
import initStoryshots, { snapshotWithOptions } from '@storybook/addon-storyshots'

initStoryshots({
  test: snapshotWithOptions({
    createNodeMock: (element) => {
      if (typeof element.type === 'string') {
        return document.createElement(element.type)
      }
    },
  }),
})

Running npm test fails with message:

  ● Storyshots › react-beautiful-dnd › Draggable

    Invariant failed: DragHandle could not find drag handle element
stale[bot] commented 6 years ago

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

stale[bot] commented 6 years ago

Hey there, it's me again! I am going close this issue to help our maintainers focus on the current development roadmap instead. If the issue mentioned is still a concern, please open a new ticket and mention this old one. Cheers and thanks for using Storybook!

goldo commented 6 years ago

@ttoohey did you find any solution ? thx

goldo commented 6 years ago

Ok I think I got it :D

const createNodeMock = element => {
  const elm = document.createElement(element.type)
  elm.setAttribute('data-react-beautiful-dnd-drag-handle', '0')
  return elm
}
ttoohey commented 6 years ago

@goldo thanks for that!

I needed to adapt the solution slightly as it introduced a new problem when applied to a more complex application. I'm now using

createNodeMock: (element) => {
  if (typeof element.type === 'string' && element.type === 'div') {
    const elm = document.createElement(element.type)
    elm.setAttribute('data-react-beautiful-dnd-drag-handle', '0')
    return elm
  }
},

Without the additional element.type === 'div' check I was getting

    TypeError: Cannot read property 'replaceChild' of null

      3 | function renderWithOptions(options) {
      4 |   return function({ story, context, renderTree }) {
    > 5 |     const result = renderTree(story, context, options);
      6 |     if (typeof result.then === "function") {
      7 |       return result;
      8 |     }

      at Typekit.componentDidMount (node_modules/react-typekit/lib/Typekit.js:58:31)