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

initial data & setData for composite & class components #1880

Closed
wants to merge 1 commit into from

Conversation

AWoelfel
Copy link

I want to be able to use setData and mount/shallowmount data: () => {} callbacks to modify data in my composite and class components.

This should handle:

@netlify
Copy link

netlify bot commented Nov 21, 2022

Deploy Preview for vue-test-utils-docs ready!

Name Link
🔨 Latest commit 276a38a
🔍 Latest deploy log https://app.netlify.com/sites/vue-test-utils-docs/deploys/637b78877f792c00096b665b
😎 Deploy Preview https://deploy-preview-1880--vue-test-utils-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site settings.

Copy link
Member

@cexbrayat cexbrayat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I mentioned in #1879 , I don't think supporting setData/initial data on components written with Composition API really makes sense, as the data field no longer exists in these components.

But I don't think strongly about it. @lmiller1990 @freakzlike what do you think ?

The same thing can be achieved via wrapper.vm.prop = value

Copy link
Collaborator

@freakzlike freakzlike left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't feel comfortable using data/setData for Composition API. Maybe using a different name/functions for this?

IIRC it's also possible to mix data with setup function somehow

}
})

app.mixin(mixin)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this be called for every component? Not only the component which has been passed to mount

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right, as i added this as a mixin it will be called for every component in this App.
I will have a look if there is another convenient way to set the data fields.

@lmiller1990
Copy link
Member

lmiller1990 commented Nov 21, 2022

I agree with @cexbrayat, setData is data as in the Options API data function. I guess we could repurpose it.

Is there a case where you can't test your component without a setSetupData function? I haven't encountered a compelling use case so far - I usually just set the state how a user does, by triggering events, etc.

Another concern is that one of the explicit goals of the Script Setup is closed by default. Are we going against a design decision? Recently we've been broken a bunch of times by core changes - maybe this is a sign Test Utils is overstepping it's bounds.

The way Vue recommends exposing those is via defineExposes:

To explicitly expose properties in a <script setup> component, use the defineExpose compiler macro

So, if we support this, would it makes sense to call it setExposes or setExposedData? You'd need to call defineExposes on whatever variables you'd like to modify in your tests, though. WDYT @AWoelfel?

@lmiller1990
Copy link
Member

Left a comment ^

Interested in this but would like to at least discuss a tiny bit more - any new feature is more complexity and maintenance so we should carefully consider based on use cases, edge cases, back/forward compatibility, etc.

@merkle-rking
Copy link

merkle-rking commented Apr 5, 2023

Is there a case where you can't test your component without a setSetupData function? I haven't encountered a compelling use case so far - I usually just set the state how a user does, by triggering events, etc.

We've recently migrated from Vue 2 to Vue 3 and are embracing knowing what to test given the changes when moving to the Composition API. It's been quite a mentality switch from our 100% line coverage approach in the Options API.

Today, I may have run into such a case where having access to the underlying data in the setup() would be helpful, if not necessary. I'm trying to write tests around a file input component. The file input's value cannot be directly modified for security reasons:

InvalidStateError: This input element accepts a filename, which may only be programmatically set to the empty string.

I'm having trouble figuring out how to get the input populated with a File() object in our tests so I can test various things (validation, the file being passed through to an API call upon form submission, etc.). Any thoughts on how to bridge this gap would be appreciated, but it may be the use-case you're looking for.

I should also mention that while we have been able to adapt to the idea that we have to emulate user actions to set values in controls, i.e. element.trigger('click'), element.setValue('foo'), etc, there's a noticeable friction in this testing when compared to the old methodology. As an example, Vuetify 3.1 recently made some changes to some of their controls and layouts that are really unimportant to us from an implementation standpoint. They changed some of the control activation events from "click" to "mousedown". These have the same effect in a browser and are almost entirely transparent to the user. For us developers, this means our tests failed upon upgrade and we had to refactor our emulated user actions. In the Options API, we would have just set the data directly with the expectation that our controls' internals are unimportant. Locating elements used in Teleports is another such example. Instead of finding an array of elements and clicking on all of them, we would've just set the data to an array in our tests.

Admittedly, the new approach gives us the stronger assertion that our controls are correctly tied to data elements because we're forced to interact with the control to engage the data.

@merkle-rking
Copy link

Coincidentally, I may have stumbled on a second use-case. We have a component that allows for updating a resource server-side. When that resource is updated, the change is logged. On the front-end, we have a View that renders both that resource and the log of the changes to the resource. When the resource is changed, we also want to have the log events on page get refreshed. The log events rendering is abstracted into its own separate component. To facilitate the forced re-render, we're using they key-changing technique. Within our tests for the main View, the log component is stubbed. The testing for the log component is separated. Our snapshots in the main View contain the stubbed representation of our log component, but because there is no representation of the :key in the stub, we're unable to test that when a user does an action in the main View, it forces a re-render of the log component. One alternative solution to exposing setup() data would be to have :key be reflected in the stub so we can assert against the value incrementing in our snapshots when we initiate user clicks. We could of course mount the log component directly in the main View's tests, but it's much cleaner to separate the concerns.

@cexbrayat
Copy link
Member

Superseeded by #2166

@cexbrayat cexbrayat closed this Aug 22, 2023
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 this pull request may close these issues.

None yet

5 participants