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

Error: Expected VDOM node to be a DOM node but got function Ref(props) #247

Open
rrrnld opened this issue Feb 15, 2023 · 5 comments
Open

Comments

@rrrnld
Copy link

rrrnld commented Feb 15, 2023

I have set up a project using vite, vitest, preact, enzyme and this very adapter. You can find a small(-ish) repository to reproduce a problem I encountered here: https://github.com/heyarne/vitest-semantic-ui-preact

The repository contains two components. For one tests work fine, for the other they don't. I have detailed this in the README of the linked repository.

npm test src/Counter.test.jsx # works fine, pure preact component
npm test src/SemanticButton.test.jsx # does not work

The second command is failing with the message given in this issue's title. The difference is that I'm trying to use a component from https://github.com/Semantic-Org/Semantic-UI-React/, which somehow confuses enzyme-addapter-preact-pure (vite build works fine, but mounting the component in a test does not). The full error message is this:

 FAIL  SemanticButton.test.jsx > SemanticButton > should mount component
Error: Expected VDOM node to be a DOM node but got function Ref(props) {
  var children = props.children,
      innerRef = props.innerRef,
      rest = (0, _objectWithoutPropertiesLoose2.default)(props, _excluded);
  var child = React.Children.only(children);
  var ElementType = ReactIs.isForwardRef(child) ? _RefForward.RefForward : _RefFindNode.RefFindNode;
  var childWithProps = child && rest && Object.keys(rest).length > 0 ? /*#__PURE__*/React.cloneElement(child, rest) : child;
  return /*#__PURE__*/React.createElement(ElementType, {
    innerRef: innerRef
  }, childWithProps);
}
 ❯ rstNodeFromVNode ../node_modules/enzyme-adapter-preact-pure/build-cjs/src/preact10-rst.js:73:15
 ❯ ../node_modules/enzyme-adapter-preact-pure/build-cjs/src/preact10-rst.js:50:21
 ❯ rstNodesFromChildren ../node_modules/enzyme-adapter-preact-pure/build-cjs/src/preact10-rst.js:42:18
 ❯ rstNodeFromComponent ../node_modules/enzyme-adapter-preact-pure/build-cjs/src/preact10-rst.js:136:22
 ❯ rstNodeFromVNode ../node_modules/enzyme-adapter-preact-pure/build-cjs/src/preact10-rst.js:70:16
 ❯ ../node_modules/enzyme-adapter-preact-pure/build-cjs/src/preact10-rst.js:50:21
 ❯ rstNodesFromChildren ../node_modules/enzyme-adapter-preact-pure/build-cjs/src/preact10-rst.js:42:18
 ❯ rstNodeFromComponent ../node_modules/enzyme-adapter-preact-pure/build-cjs/src/preact10-rst.js:136:22

It looks like the issue is similar to #61, but I'm not entirely sure how both relate to each other.

The component raising the error is (I think) this one: https://github.com/microsoft/fluentui/blob/1a0f15ed7ea41974e3ef6cf83138b60656dacd7c/packages/fluentui/react-component-ref/src/Ref.tsx Any idea why this confuses this adapter? Is there anything I can do about it?

Thanks in advance!

@robertknight
Copy link
Member

robertknight commented Feb 15, 2023

From modifying the code in node_modules/enzyme-adapter-preact-pure/build-cjs/src/preact10-rst.js to log the value of node just before it throws an error, I see this:

VNode {
  '$$typeof': Symbol(react.element),
  type: [Function: Ref],
  key: null,
  ref: null,
  props: {
    innerRef: { current: null },
    children: {
      '$$typeof': Symbol(react.element),
      type: 'button',
      key: null,
      ref: null,
      props: [Object],
      _owner: null,
      _store: {}
    }
  },
  _owner: null,
  _store: {}
}

This to me looks like a React VNode rather than a Preact one.

A typical Preact node has a bunch of __-prefixed properties like this:

{
  type: [Function: ButtonExampleButton],
  props: {},
  key: undefined,
  ref: undefined,
  __k: null,
  __: null,
  __b: 0,
  __e: null,
  __d: undefined,
  __c: null,
  __h: null,
  ...
}

So I suspect that somehow the bundle might contain both React and Preact. If there is a way to actually look at the transformed code that Node is executing, that would make it easier to find out what is going on.

@rrrnld
Copy link
Author

rrrnld commented Feb 15, 2023

Thanks for the quick reply! I tried aliasing react and react-dom to @preact/compat like so, but that didn't change anything:

Click to view diff
diff --git a/package-lock.json b/package-lock.json
index 0db89d6..82772df 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,7 @@
       "version": "1.0.0",
       "license": "ISC",
       "devDependencies": {
+        "@preact/compat": "^17.1.2",
         "@preact/preset-vite": "^2.5.0",
         "enzyme": "^3.11.0",
         "enzyme-adapter-preact-pure": "^4.1.0",
@@ -859,6 +860,15 @@
         "url": "https://opencollective.com/popperjs"
       }
     },
+    "node_modules/@preact/compat": {
+      "version": "17.1.2",
+      "resolved": "https://registry.npmjs.org/@preact/compat/-/compat-17.1.2.tgz",
+      "integrity": "sha512-7pOZN9lMDDRQ+6aWvjwTp483KR8/zOpfS83wmOo3zfuLKdngS8/5RLbsFWzFZMGdYlotAhX980hJ75bjOHTwWg==",
+      "dev": true,
+      "peerDependencies": {
+        "preact": "*"
+      }
+    },
     "node_modules/@preact/preset-vite": {
       "version": "2.5.0",
       "resolved": "https://registry.npmjs.org/@preact/preset-vite/-/preset-vite-2.5.0.tgz",
@@ -4060,6 +4070,13 @@
       "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==",
       "dev": true
     },
+    "@preact/compat": {
+      "version": "17.1.2",
+      "resolved": "https://registry.npmjs.org/@preact/compat/-/compat-17.1.2.tgz",
+      "integrity": "sha512-7pOZN9lMDDRQ+6aWvjwTp483KR8/zOpfS83wmOo3zfuLKdngS8/5RLbsFWzFZMGdYlotAhX980hJ75bjOHTwWg==",
+      "dev": true,
+      "requires": {}
+    },
     "@preact/preset-vite": {
       "version": "2.5.0",
       "resolved": "https://registry.npmjs.org/@preact/preset-vite/-/preset-vite-2.5.0.tgz",
diff --git a/package.json b/package.json
index 4901442..8104ef3 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
   "author": "",
   "license": "ISC",
   "devDependencies": {
+    "@preact/compat": "^17.1.2",
     "@preact/preset-vite": "^2.5.0",
     "enzyme": "^3.11.0",
     "enzyme-adapter-preact-pure": "^4.1.0",
diff --git a/vite.config.js b/vite.config.js
index d57336c..fa6cd22 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -26,6 +26,14 @@ export default defineConfig({
       {
         find: 'preact/hooks',
         replacement: require.resolve('preact/hooks')
+      }, 
+      {
+        find: 'react',
+        replacement: '@preact/compat'
+      },
+      {
+        find: 'react-dom',
+        replacement: '@preact/compat'
       }
     ],
   },

Any other idea what to try?

@robertknight
Copy link
Member

Any other idea what to try?

Can you find out how to look at the bundled code that Vitest actually runs, after it has processed JSX etc. That should make debugging easier.

@rrrnld
Copy link
Author

rrrnld commented Feb 15, 2023

This is the output of running npm run vite build in the respository linked above. I can at least find references to Symbol.for("react.element"), but I don't really know what to do with the output: dist/assets/main-877ad57b.js

I have an idea where it's coming from, but I don't know what to do with that information: @fluentui/react-component-ref is distributed with a single other module, react-is, which contains the snippet var b="function"===typeof Symbol&&Symbol.for,c=b?Symbol.for("react.element") that I think shows up in the bundle.

EDIT Feel free to ignore this; this is not the code that vitest runs.

@rrrnld
Copy link
Author

rrrnld commented Feb 16, 2023

OK, I figured out how to view the code (for future reference: Run vitest --ui, navigate to the test you're interested in, click on the "module graph" tab and click on any of the modules). These are the compiled modules:

SemanticButton.jsx (original):

var _jsxFileName = "/tmp/vitest-semantic-ui-react/src/SemanticButton.jsx";
const __vite_ssr_import_0__ = await __vite_ssr_import__("preact");

const __vite_ssr_import_1__ = await __vite_ssr_import__("semantic-ui-react");

const __vite_ssr_import_2__ = await __vite_ssr_import__("preact/jsx-dev-runtime");

const ButtonExampleButton = () => __vite_ssr_import_2__.jsxDEV(__vite_ssr_import_1__.Button, {
  children: "Click Here"
}, void 0, false, {
  fileName: _jsxFileName,
  lineNumber: 4,
  columnNumber: 35
}, void 0);
__vite_ssr_exports__.default = ButtonExampleButton;

//# sourceMappingSource=vite-node

SemanticButton.test.jsx (original):

var _jsxFileName = "/tmp/vitest-semantic-ui-react/src/SemanticButton.test.jsx";
const __vite_ssr_import_0__ = await __vite_ssr_import__("vitest");

const __vite_ssr_import_1__ = await __vite_ssr_import__("preact");

const __vite_ssr_import_2__ = await __vite_ssr_import__("enzyme");

const __vite_ssr_import_3__ = await __vite_ssr_import__("/SemanticButton.jsx");

const __vite_ssr_import_4__ = await __vite_ssr_import__("preact/jsx-dev-runtime");

__vite_ssr_import_0__.describe("SemanticButton", () => {
  __vite_ssr_import_0__.test("should mount component", () => {
    const wrapper = __vite_ssr_import_2__.mount(__vite_ssr_import_4__.jsxDEV(__vite_ssr_import_3__.default, {}, void 0, false, {
      fileName: _jsxFileName,
      lineNumber: 9,
      columnNumber: 27
    }, this));
    __vite_ssr_import_0__.expect(wrapper.text()).to.include("Click here");
  });
});

//# sourceMappingSource=vite-node

Nothing unexpected, as far as I can tell?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants