I am confused about how to test Vue components with Vue Testing Library.
For example, I hava a parent component with a lot of children components, and in the parent component, I do many things, such as search and display data, add data, delete data, update data...
So, should I test parent component or children components?
And if I test parent component, how to mock the request(using axios) in the mounted function?
Help me answer my questions.
Related
In my vue cli project I have a route Settings with 3 child components SettingsA, SettingsB and SettingsC. Each child component has ca. 15 input fields, so it would be too many input fields for one single component.
The goal is to get data from a REST backend with an an axios call when the Route Settings is loaded, and populate some of the input fields with the data;
the user can then navigate between the child components and fill/change the input fields, without triggering the axios call which would reload and overwrite the users input field changes.
Since there are 3 child components I use vuex as store. That way the users inputs should not change when he navigates between the child components.
My question is: Where and with what hook should I make the axios call? With beforeMounted on the Settings Component?
Maybe there is also a better, already tried design than mine?
Thanks for your help!
Solution using custom events
You actually not necessarily need vuex. Basic idea is to have parent component Settings, which includes SettingsA, SettingsB and SettingsC, which are displayed conditionally using v-if. The Settings component is holding your state. Changes in the child components form fields trigger events with this.$emit(). The parent component listens to the events and updates its state. The state of the form is passed down via props.
Solution using Vuex actions
If you go the Vuex route, you will trigger actions instead of using this.$emit() and update the global store. You should import the actions using mapActions. In your components you then have access to the global store using this.$store.
I'm confused about best practices for passing data from parent to child components and modularity strategies.
As I know there are 2 ways:
Fetching data in parent component and send Array/object to the child via props
Send parent_id to the child via props and fetching data within the child component
Let's assume a use case working with a product edit view, having:
A parent component product
A child form component to edit basic product information
A child related_products component where other products can be linked/unlinked.
As per my experience, the first way works smoothly since it's all done in 1 request to the API: fetching a product object in parent component and passing through props the product itself to the form component and the nested objects to the related_products component. In addition, it can be done in beforeRouteEnter guard so the parent and all its children are shown with all the information at once. The cons I see here is that we have to send the correct object structure to the child component to avoid any error, having a strong dependency between components.
On the other hand, by sending the parent_id to every child component through props we release the parent from any logic. In this case, every child component acts as a "black box" and fetch/handles the information. The cons I see here is that we would have to perform 2 API requests for getting the product and the related products. In addition, the beforeRouteEnter is not viable at all, so we get an empty form/table until the data is retrieved.
This is not about how to code it, it's just about what's the best implementation as per your experience.
As far as my experience is concerned, 1-st way is better. Parent component acts as "smart" and you have access to it's life cycle hooks in order to trigger your api-requests, reset timers, e.t.c... I would also suggest to use vuex, as it allows you to make clean interface of communication between your parent component and "outer world", utilizing actions and getters.
With that being said, your "dumb" child component communicates with it's parent through props and emits interface. And because it is "dumb" - it's easier to test it or utilize something like "storybook".
we have to send the correct object structure to the child component to avoid any error
I guess, at the end of the day, you'll need correct object structure anyway, right? It could not be just random...
I am learning Vue and my doubt is about the structure of my Vue app.
I learnt that the components can include both logic and template. Then I separated my components and everyone is getting the config from the main app (config is an object with the coordinates config.ll, config.lng).
I do the ajax call to my search-and-discovery API service and I display the results inside each components (current location, venues-near-you etc).
My question is: is it correct to encapsulate the calls into each components? Or is it better to get the needed data inside the general app and then share the results with the components using pros?
I am asking that because the hard part is starting now when I want to communicate the click of a category to the venuesNearYou component, I tried to use the emit without success.
//MAIN
<sidebar :config="config"></sidebar>
<content :config="config"></content>
//IN SIDEBAR
<currentLocation :config="config"></currentLocation>
<categories :config="config"></categories>
//IN CONTENT
<venueDetails :config="config"></venueDetails>
<venuesNearYou :config="config"></venuesNearYou>
I think you could use event Bus like approach
we have three type of communication in vue app (without vuex)
Parent to child communication which is full field by props
child to parent communication handle by custom event from child which is listen by parent
communication between non parent child component in which we use event bus approach
Parent to child example
Child to parent example
In child this.$emit('sendDataToParent',{someData:"some data"}})
in parent
<child-component :somedata="dataToChild" #sendDataToParent="'gotsomedata from parent'">
Event Bus
in main vue instance
const eventBus = new Vue()
in some component from where to send data
import eventBus
eventBus.$emit('someEvent','some data')
in some component from where to receive data
created() {
// register listener
eventBus.$on('someEvent',()=>{
})
}
For more reference
https://v2.vuejs.org/v2/guide/components.html#Passing-Data-to-Child-Components-with-Props
https://v2.vuejs.org/v2/guide/components.html#Emitting-a-Value-With-an-Event
https://medium.com/easyread/vue-as-event-bus-life-is-happier-7a04fe5231e1
It's hard to help you around emitting an event since you didn't provide much of a code. But check Vuex. It serves as a centralized store for all the components in Vue application.
I am working on a Vue Application which has nested components.
I am using Jest for writing Unit test cases.
While executing unit test cases on a parent component, i noticed the child components are not loaded.
I am using shallow rendering in test suites.
Please share any links or tutorials on this topic.
Thanks
a) Use mount instead of shallow
b) Import the child component at the top of the spec.js file, just as you did with the parent
I'm new to vue js and have some questions when learning it.
I'm now a little confused about the relationship between its instance and component. As far as I learned, every app build by vue should only have one instance and one instance only, it can have as many components as you like if needed. But recently I've seen a demo, and in that demo it has more than one instance.
So my question is, is that ok to have multiple intances in one app( the demo code works fine, but is that the correct way)? What's the best practice to use instance and component in vue app?
It's ok to have two instances in the same project, however, you probably don't want to do that.
A good scenario is to have one main instance to control your app, specially if you are creating a Single Page Application (SPA). Then use as many components as you want.
Components are a great way to reuse code and keep it organized, and, with Vue.js, is very easy to communicate between your components and your "main" Vue instance.
It depends very much on your situation.
I work on a large web project which is not an SPA. We have a Vue instance for each "silo" of the application. We are slowly transitioning an older project from a mostly jQuery frontend so it's possible that as it evolves We'll be able to condense down to a single Vue instance but we're having no trouble with multiple instances. The ease of using Vue in existing projects was one of the biggest deciding factors in choosing it over another library such as react.
I have taken a different approach with green development, one instance and many components.
There are something in common, and some difference between Vue instance and Vue component.
From Vue docs:
all Vue components are also Vue instances, and so accept the same options object (except for a few root-specific options).
The root Vue instances accept properties like el, router, the Vue components cannot.
The data property in root Vue instances is an object, but in Vue components must be a function.
The design target is different:
A root Vue instance is a Vue application launcher, Vue component is an extension of the Vue instance.
Vue components can create elements to be reused in many places. This is Vue characteristic of componentization mainly reflect point.
Vue instance can associated with and manipulate an element which is already exist.
Vue component more suitable for create new element and reuse it at anywhere.
Think of a Vue Component as a blueprint or set of rules on how to create something that can be inserted into the DOM that the user can interact with.
So when you create a Vue file you are going to define exactly one component with a set of rules that tells Vue how to display stuff on the screen and tells a user how to interact with it.
On the other hand is a Vue instance, its an instance of a Vue component, it represents something that has been inserted into the DOM and is something that a user can interact with.
If you have a background in Object-Oriented Programming, think of a Vue Component as being like a class and a Vue instance as an instance of that class.
What has not been mentioned in previous answers that I will cover in regards to the difference between Vue instance and Vue component is how we define the data property that we are working with.
If we are working with a Vue instance, then we can define the data property as an object or a function that returns an object like so:
With a Vue Component that data property must be a function that returns an object.
So for example this is a Vue component:
export default {
name: "App",
components: {
SearchBar,
VideoList
},
And if we want to make use of data inside of that Vue component, we have to make a function that returns an object.
Vue components extends Vue instances
but Vue instances accept properties like el, router, the Vue components cannot.
best practice:
one Vue instance
many Vue component