Reputation: 142
I’m using Cypress in my Vue.js project (Nuxt.js). The main problem I can’t managed is how to understand the vuex store is ready. Let’s say I have a button that can call axios to fetch some data. Then the data came in to the store by mutations and Vue will render it in a template. The next element I want to interact with is empty before the store has built. But the cypress is trying to check it.
How to call next cypress action (like cy.get) after the store has built?
My project is more complicated. But the core problem is that cypress sometimes don’t wait for store building and trying to work further. For the first time we have used cy.wait(1000)
, but it seems not so perfect decision.
<div>
<button data-cy="fetchDataBtn" @click="fetchData">get items</button>
<ul>
<li v-for="item in items">
<p>{{ item.title }}</p>
<button
@click="fetchProduct(item.id)"
>
buy {{ item.name }}
</button>
</li>
</ul>
</div>
<script>
import { mapState } from 'vuex';
export default {
name: 'App',
computed: {
...mapState('list', ['items'])
}
}
</script>
I expect the scenario below:
cy.get([‘data-cy=fetchDataBtn’]).click()
// wait for store is ready and list is already rendered
// (NOT cy.wait('GET', 'url_string') or cy.wait(milliseconds))
cy.contains(‘button’, 'buyItemName').click()
Upvotes: 4
Views: 3715
Reputation: 23473
Take a look at this post Testing ... with Vuex Store ..., the key is to add a reference to the Vue app to window,
const app = new Vue({
store,
el: '.todoapp'
//
})
if (window.Cypress) {
// only available during E2E tests
window.app = app
}
then test the store for appropriate keys before proceeding the test the DOM
const getStore = () => cy.window().its('app.$store')
it('has loading, newTodo and todos properties', () => {
getStore().its('state').should('have.keys', ['loading', 'newTodo', 'todos'])
})
However, it can be even simpler than that!
You say
The next element I want to interact with is empty before the store has built.
With the right combination of commands, Cypress will wait for content fetched via axios, as long as you choose the correct 'indicator' element and test it's content, for example
cy.contains('my.next.element.i.want.to.interact.with', 'the.content.fetched.with.axios', { timeout: 10000 })
This waits up to 10 seconds for the fetched content to show (or less if it appears earlier). Without a timeout param, it waits up to 5 secs, which could be enough.
NOTE, there is a subtle trap with Cypress chained commands.
Don't use
cy.get('my.next.element.i.want.to.interact.with')
.contains('the.content.fetched.with.axios')
because your Vue template probably has the element tag or class from the start, but it's content is initially empty and this pattern will not wait for the content you want to see. It will simply compare initial content (nothing) without waiting for the fetch to complete.
Upvotes: 6