Skip to content

setData function with class components returns TypeError #572

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

Closed
Evertvdw opened this issue May 5, 2021 · 3 comments
Closed

setData function with class components returns TypeError #572

Evertvdw opened this issue May 5, 2021 · 3 comments

Comments

@Evertvdw
Copy link
Contributor

Evertvdw commented May 5, 2021

Hi there,

I got vue-jest to work so I continued to see if I could get unit tests working in my codebase. I stumbled upon the next issue, I saw this was also reported when using the Composition api but I get the same error with class components:

I'm doing this inside a test:
await wrapper.setData({ hovered: true });

Which results in this error:
TypeError: Cannot add property hovered, object is not extensible

Component looks like (simplified):

import { Vue } from 'vue-class-component';

export default class Test extends Vue {
     hovered = false;
}

So hovered is equivalent to what in the Options API would be data. So I would expect this to work.

Reproduce

You can reproduce this in the vue-test-utils codebase by adding these two lines:

await wrapper.setData({dataText: 'Test'})
expect(wrapper.get('[data-methods]').text()).toBe('Test')

at the end of the works with shallow mount and SFC test in classComponent.spec.ts.

@Evertvdw
Copy link
Contributor Author

Evertvdw commented May 5, 2021

A quick dive into this learn that with class components the vm.$data which is accessed in the setData method is empty. The data properties are just present on the vm object itself with a getter and setter.

Just doing this in the code works instead of using setData

(wrapper.vm as any).hovered = true;
await (wrapper.vm as any).$nextTick();

It's not very nice and clean but for class components it seems that everything is just placed on the vm object and not in the vm.$data object.

What you could do is check in setData for each property passed if vm.hasOwnProperty() is true, and if so update it. This might be needed for Composition api components also, see #539

@lmiller1990
Copy link
Member

Thanks for the issue report.

There are a number of known problems with class component. Another one is mocks not working correctly, see here. The main problem is setData assumes you are using an object component with a data property. As you pointed out, the way class components store data is a bit different (makes sense, classes have a built in way to store data).

If we can get class component to work correctly using setData, that would be great.

@Component
export default class App extends Vue {
  someData = this.$t("message");
}

Should this.$ properties be configurable with setData, too?

Could we just have a check in setData? Kind of like you suggested? Maybe not the cleanest but class component is already a bit of a dirty hack anyway.

if (this.isClassComp) {
  this.vm[key] = value
  await this.vm.$nextTick()
} else {
  // usual stuff
}

@lmiller1990
Copy link
Member

More or less dup: #1058

Going to merge all class component issues.

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