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

using shallowMount on a component that uses Symbol causes tests to crash #1076

Closed
liamdebeasi opened this issue Nov 16, 2021 · 2 comments · Fixed by #1086
Closed

using shallowMount on a component that uses Symbol causes tests to crash #1076

liamdebeasi opened this issue Nov 16, 2021 · 2 comments · Fixed by #1086

Comments

@liamdebeasi
Copy link

When using shallowMount on a component that uses Symbol as a value for a property, Vue Test Utils fail to run. I receive the following error:

 TypeError: Failed to execute 'setAttribute' on 'Element': parameter 2 is a symbol, which cannot be converted to a string.

      at Object.exports.DOMString (node_modules/webidl-conversions/lib/index.js:228:15)
      at patchAttr (node_modules/@vue/runtime-dom/dist/runtime-dom.cjs.js:207:16)
      at patchProp (node_modules/@vue/runtime-dom/dist/runtime-dom.cjs.js:406:9)
      at mountElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3751:25)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3724:13)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3644:21)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4181:21)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:164:29)
      at setupRenderEffect (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4300:9)

I would expect there to be no error when using shallowMount. When using mount, the tests run as expected.


Steps to reproduce:

  1. Clone https://github.com/liamdebeasi/vue-test-utils-symbol.
  2. Run npm install.
  3. Run npm run test:unit. Observe that the tests fail on the error above.
  4. Open src/MyCmp.vue and change the default value for myProp from Symbol() to '123'.
  5. Run npm run test:unit. Observe that the tests pass as expected.

This is a blocker for some Vue users upgrading to Ionic 6, so it would be great if this could get fixed: ionic-team/ionic-framework#24181. We make use of Symbols to account for this change in behavior with Vue 3.1: vuejs/core#3889

@lmiller1990
Copy link
Member

lmiller1990 commented Nov 17, 2021

Weird, this is working fine for me in this code base:

  it.only('works with Symbol as default', () => {
    const Comp = defineComponent({
      template: `<div>Symbol: {{ sym }}</div>`,
      props: {
        sym: {
          type: Symbol,
          default: Symbol()
        }
      }
    })

    const wrapper = mount(Comp, { shallow: true })

    expect(wrapper.html()).toBe('<div>Symbol: Symbol()</div>')
  })

I don't think this is a bug in Test Utils? Or at least, not just Test Utils, but some combination of libraries. Looking at your stack trace:

at Object.exports.DOMString (node_modules/webidl-conversions/lib/index.js:228:15)

Specifically, the error is here: https://github.com/jsdom/webidl-conversions/blob/cb1bfe6ddf23d4f4eb44781ff55a4c337d2ae0a5/lib/index.js#L246.

I'm not entirely sure of the cause. We will need to explore more. Very weird.

You might want to try updating your deps - the repo is on Jest 24.x, which is quite a few majors behind, as well as the jsdom and webidl library. Not sure if that's related, though.

@lmiller1990
Copy link
Member

lmiller1990 commented Nov 17, 2021

I cannot reproduce: https://github.com/vuejs/vue-test-utils-next/compare/issue-1076?expand=1 🤔 any ideas?

Edit: follow progress here: ionic-team/ionic-framework#24181. Copy pasting here:

Basically the problem is we do something like this (only for stubs):

<some-stub sym="Symbol()" />

Which is not valid in jsdom, you cannot serialize a symbol (according to their implementation). I don't really see any good solution here... the problem is basically that the attribute serializer in jsdom chooses to error here. Any ideas?

We are not the first ones to run into this: jsdom/webidl-conversions#14. We might need to add some kind of escape hatch or hack into Test Utils for this, I'm not entirely sure how to proceed.

What we could do is have a "dumb stubs" config option, so instead of attempting to spread props over a stub, like I described above, you'd just get no props. It would solve this problem, but you wouldn't get props on your stubs (which I think is fine. Something like:

import { config } from '@vue/test-utils'
// global
config.global.noPropsOnStubs = true

// per test
shallowMount(Comp, {
  global: {
    noPropsOnStubs: true
  }
})

Still not great, but there's basically no chance jsdom will change this, and I don't see another good option really.

Maybe we should try using https://www.npmjs.com/package/happy-dom and see what happens? Be interesting to how they handle the Symbol attribute case.

cexbrayat added a commit to cexbrayat/vue-next that referenced this issue Nov 18, 2021
Currently, passing a `Symbol` to an attribute throws in `runtime-dom` with:

```
TypeError: Failed to execute 'setAttribute' on 'Element': parameter 2 is a symbol, which cannot be converted to a string.
```

This is because the underlying library used for conversion does not handle Symbol (see jsdom/webidl-conversions#14).

This issue cascades into VTU-next as `shallowMount` attempts to write props values as attributes.
See vuejs/test-utils#1076 for more context.
cexbrayat pushed a commit that referenced this issue Dec 13, 2021
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

Successfully merging a pull request may close this issue.

2 participants