Code Monkey home page Code Monkey logo

Comments (22)

atomiks avatar atomiks commented on May 11, 2024 3

This seems to work (tested it):

export function isVirtualElement(value) {
  return (
    {}.toString.call(value) === '[object Object]' && !value.addEventListener
  )
}

Virtual objects passed to tippy won't have addEventListener, but jsdom objects do.

from tippyjs-react.

atomiks avatar atomiks commented on May 11, 2024 3

A fix for this was released in 4.0.3 of the native library

from tippyjs-react.

atomiks avatar atomiks commented on May 11, 2024 1

Can you post the component here?

from tippyjs-react.

KubaJastrz avatar KubaJastrz commented on May 11, 2024 1

I have been testing Tippy with enzyme (only shallow though) for a while now. I will post a working example later today if you want.

from tippyjs-react.

atomiks avatar atomiks commented on May 11, 2024

polyfillElementPrototypeProperties

This means tippy() is receiving a plain object {} instead (maybe React element object?) of a DOM node

from tippyjs-react.

dmc1985 avatar dmc1985 commented on May 11, 2024

Thank you for your quick response. I see that when I use enzyme's mount, it returns a plain object which is causing the error per your explanation above. Is it possible to modify this plain object (such as adding a method) to prevent the error so that I may create working tests using the Tooltip component I created based on Tippy?

from tippyjs-react.

dmc1985 avatar dmc1985 commented on May 11, 2024

Here is the code for the component:

function Tooltip(props) {
    return (
        <Tippy
            arrow={false}
            allowHTML={true}
            animateFill={false}
            animation='shift-away'
            duration={300}
            maxWidth="130px"
            placement={props.placement}
            theme={props.theme}
            content={(
                <div data-brain='tooltip'>
                    <div className='tooltip-content'>
                        <p className='title'>{props.title}</p>
                        <p className='content'>{props.content}</p>
                    </div>
                </div>
            )}
        >
            {props.children}
        </Tippy>
    );
}

And here is the code for the test that causes the problem:

import { mount } from 'enzyme'; 
wrapper = mount(
            <Tooltip
                content="content"
                theme="light"       
                title="title"
                placement="bottom"
            >
                <Button>Test</Button>
            </Tooltip>
        )

from tippyjs-react.

atomiks avatar atomiks commented on May 11, 2024

Hm can you show the code for <Button>?

from tippyjs-react.

dmc1985 avatar dmc1985 commented on May 11, 2024

Here is the code for the Button component:

function Button(props) {
    const { children, type, disabled, ...otherProps } = props;
    const submit = type === 'classic' ? 'submit' : 'button';
    return (
        <button
            data-brain="button"
            className={disabled ? 'disable' : `button-${type}`}
            type={submit}
            disabled={disabled}
            {...otherProps}
        >
            {children}
        </button>
    );
}

However, I don't think this component is the source of the problem because if I put any sort of HTML element as the child of the Tooltip component in the argument for enzyme's mount. I tested it with

Test
and I got the same error as the title of this issue. The tests only pass when I use plain text that is not placed inside html.

I also added the tooltip to a Card component, and when I run the tests on this Card component which involve using enzyme's mount (these tests were all passing before adding the Tooltip) and now these tests fail. Here's the snippet of my use of the Tooltip in this Card component:

      ```
        <Tooltip
            content={props.title}
            placement='bottom'
            theme='dark'
        >
            <h4>{props.title}</h4>
        </Tooltip>

from tippyjs-react.

atomiks avatar atomiks commented on May 11, 2024

Try editing node_modules/@tippy.js/react/dist/Tippy.js and add

console.log(ReactDOM.findDOMNode(this))

in cDM and run the tests to see what's being passed

from tippyjs-react.

dmc1985 avatar dmc1985 commented on May 11, 2024

Per your request, I added console.log(ReactDOM.findDOMNode(this)) to the componentDidMount lifecycle method of node_modules/@tippy.js/react/dist/Tippy.js (line 138). Here is the console.log in context just to be sure we're on the same page:

_createClass(Tippy, [{
      key: "componentDidMount",
      value: function componentDidMount() {
        console.log('console test', ReactDOM.findDOMNode(this))
        this.setState({
          isMounted: true
        });

Here is what I see in my console:

console test HTMLDivElement {
      '__reactInternalInstance$b72ohub83fu': 
       ....[omitted]
}

from tippyjs-react.

atomiks avatar atomiks commented on May 11, 2024

Okay, that's strange I guess... I don't know why it's seeing it as a plain object (which uses the naive check {}.hasOwnProperty.call(ReactDOM.findDOMNode(this)) === '[object Object]' - maybe log that out?)

If all else fails, I'd suggest switching to react-testing-library instead of enzyme (that's what I switched to to test this library because enzyme was giving me other troubles)

from tippyjs-react.

atomiks avatar atomiks commented on May 11, 2024

shallow doesn't call cdM does it? So it's not actually testing the tippy call

from tippyjs-react.

atomiks avatar atomiks commented on May 11, 2024

I just set up a basic directory to test this out and didn't experience this error:

index.test.js

import React from 'react'
import Tippy from '@tippy.js/react'
import { mount, configure } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'

configure({ adapter: new Adapter() })

function Tooltip(props) {
  return (
    <Tippy
      arrow={false}
      allowHTML={true}
      animateFill={false}
      animation="shift-away"
      duration={300}
      maxWidth="130px"
      placement={props.placement}
      theme={props.theme}
      content={
        <div data-brain="tooltip">
          <div className="tooltip-content">
            <p className="title">{props.title}</p>
            <p className="content">{props.content}</p>
          </div>
        </div>
      }
    >
      {props.children}
    </Tippy>
  )
}

test('<Tippy />', () => {
  const wrapper = mount(
    <Tooltip content="content" theme="light" title="title" placement="bottom">
      <h1>example</h1>
    </Tooltip>,
  )
  expect(true).toBe(true)
})

package.json

{
  "name": "tippy-testing",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "jest --coverage"
  },
  "author": "",
  "license": "ISC",
  "jest": {
    "setupFilesAfterEnv": [
      "<rootDir>setup.js"
    ],
    "coveragePathIgnorePatterns": [
      "test/setup.js"
    ]
  },
  "dependencies": {
    "@tippy.js/react": "^1.1.1",
    "jest": "^24.0.0",
    "react": "^16.7.0",
    "react-dom": "^16.7.0"
  },
  "devDependencies": {
    "@babel/core": "^7.2.2",
    "@babel/preset-env": "^7.3.1",
    "@babel/preset-react": "^7.0.0",
    "babel-jest": "^24.0.0",
    "enzyme": "^3.8.0",
    "enzyme-adapter-react-16": "^1.8.0"
  }
}

setup.js

global.MutationObserver = class {
  constructor() {}
  disconnect() {}
  observe() {}
}

global.window.document.createRange = function createRange() {
  return {
    setEnd: () => {},
    setStart: () => {},
    getBoundingClientRect: () => {
      return { right: 0 }
    },
    getClientRects: () => [],
    commonAncestorContainer: document.createElement('div'),
  }
}

global.window.focus = () => {}
global.window.scroll = () => {}

from tippyjs-react.

dmc1985 avatar dmc1985 commented on May 11, 2024

@atomiks I tried to recreate your simple Tippy test but I got a lot of errors concerning babel and jest. Could you please upload the entire project to github so I could fork the repo?

@KubaJastrz although @atomiks is right that shallow isn't exactly what I need, I'd be curious to see your working exmaple.

from tippyjs-react.

KubaJastrz avatar KubaJastrz commented on May 11, 2024

Everything should just work -> https://github.com/KubaJastrz/tippy-testing

My general rule of thumb when using enzyme: don't use mount unless really have to (ie. using context which isn't supported 😢)

from tippyjs-react.

atomiks avatar atomiks commented on May 11, 2024

@dmc1985 sorry I forgot to mention .babelrc is:

{
  "presets": ["@babel/env", "@babel/react"]
}

But yes check @KubaJastrz

from tippyjs-react.

dmc1985 avatar dmc1985 commented on May 11, 2024

@KubaJastrz @atomiks Thanks so much for your help. From what I can tell, the problem is coming from the testing environment that I'm using because it's sending a plain object to Tippy instead of an HTML div element. When I logged console.log(ReactDOM.findDOMNode(this)) for what my test sends to tippy versus what the tests in @KubaJastrz 's repo sends, it's clear that this difference is causing the error.

from tippyjs-react.

wakame-isono avatar wakame-isono commented on May 11, 2024

@dmc1985
Hello.
I hava the same error by Vue & Jest.
I found it: jsdom/jsdom#766.
Even if it is an Element, jsdom less than 10.1.0 return [object Object] by Object.prototype.toString.call.
They supported it after 10.1.0.
See it: https://github.com/jsdom/jsdom/blob/16d3913eea0360c7757e75f7e266c3873c85b7dd/Changelog.md#1010

from tippyjs-react.

atomiks avatar atomiks commented on May 11, 2024

@wakame-isono can you setup a minimal reproduction repo for me? In the PR it looks like it should return the constructor in the string, like [object HTMLDivElement], instead of [object Object]

Regardless, if we can make this check more robust (in smallest code possible) to fix it then I welcome PRs to the native library: https://github.com/atomiks/tippyjs/blob/bfbf26003f9f9d25af25ba2a0073c65eb6590ebc/src/js/utils.js#L8-L10

from tippyjs-react.

wakame-isono avatar wakame-isono commented on May 11, 2024

@atomiks
I created a repository for the report.
https://github.com/wakame-isono/tippy-vue-testing

When yarn run test, The error and {}.toString.call(Element) result will be output to the console.

I think we should probably use jsdom over ver 10.1.0. if someone use jsdom less than ver 10.1.0, we can mock tippy.js.

for example.

Create moke file to <rootDir>/__mocks__/tippy.js.js

then

const tippy = jest.fn();

Object.defineProperty(tippy, 'setDefaults', {
  get() {
    return jest.fn();
  },
});

module.exports = tippy;

from tippyjs-react.

wakame-isono avatar wakame-isono commented on May 11, 2024

@atomiks
Sorry I am not sure virtual DOM except Vue.
But it also work well for me!! ✨✨👏👏

from tippyjs-react.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.