首页 > 解决方案 > 用 cypress 测试 vuex

问题描述

我在我的 Vue.js 项目 (Nuxt.js) 中使用赛普拉斯。我无法管理的主要问题是如何理解 vuex 存储已准备就绪。假设我有一个按钮可以调用 axios 来获取一些数据。然后数据通过突变进入存储,Vue 将其呈现在模板中。在商店建成之前,我要与之交互的下一个元素是空的。但柏树正试图检查它。

商店建成后如何调用下一个 cypress 操作(如 cy.get)?

我的项目更复杂。但核心问题是,cypress 有时不等待店铺建设,并试图进一步工作。我们第一次使用cy.wait(1000),但似乎没有那么完美的决定。

<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>

我预计以下情况:

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()

标签: vue.jsvuexcypress

解决方案


看看这个帖子Testing ... with Vuex Store ...,关键是添加对 Vue 应用程序到 window 的引用,

const app = new Vue({
  store,
  el: '.todoapp'
  //
})
if (window.Cypress) {
  // only available during E2E tests
  window.app = app
}

然后在继续测试 DOM 之前测试商店的适当键

const getStore = () => cy.window().its('app.$store')

it('has loading, newTodo and todos properties', () => {
  getStore().its('state').should('have.keys', ['loading', 'newTodo', 'todos'])
})

但是,它可以比这更简单!

你说

在商店建成之前,我要与之交互的下一个元素是空的。

使用正确的命令组合,赛普拉斯将等待通过 axios 获取的内容,只要您选择正确的 'indicator' 元素并测试它的内容,例如

cy.contains('my.next.element.i.want.to.interact.with', 'the.content.fetched.with.axios', { timeout: 10000 })

这将等待最多 10 秒以显示获取的内容(如果显示较早,则等待更少)。如果没有超时参数,它最多会等待 5 秒,这可能就足够了。

注意,赛普拉斯链式命令存在一个微妙的陷阱。

不要使用

cy.get('my.next.element.i.want.to.interact.with')
  .contains('the.content.fetched.with.axios')

因为你的 Vue 模板可能从一开始就有元素标签或类,但它的内容最初是空的,这种模式不会等待你想看到的内容。它将简单地比较初始内容(无),而无需等待获取完成。


推荐阅读