Cypress 使用来自 Pinia Vue3 的动作

Cypress using actions from Pinia Vue3

我正在从这个视频中学习一些柏树:https://www.youtube.com/watch?v=03kG2rdJYtc 我对他在 29:33 上说的话很感兴趣:“程序化登录” 但是他正在使用 vue2 和 Vuex。

我的项目是用Vite创建的,状态管理是Pinia。 那么如何使用 pinia 操作进行程序化登录?

例如欢迎登录用户应该看到仪表板:

describe('Welcome', () => {
  it('logged in user should visit dashboard', () => {
    // login
    cy.visit('/')
    cy.url().should('contain', '/dashboard')
  })
})

还有我的 userStore:

export const useUserStore = defineStore({
  id: 'user',
  state: () => ({
    username: ref(useLocalStorage('username', null)),
  }),
  getters: {
    isLoggedIn: (state) => state.username !== null,
  },
  actions: {
    login(username, password) {
      return useAuthLoginService(username, password)
        .then((response) => {
          this.username = response.username
        })
        .catch((error) => {
          return Promise.reject(new Error(error))
        })
    },
  },
})

如何在 cypress 测试中调用 login 操作? 现在作为一种解决方法,我正在写一个本地存储,如:

localStorage.setItem('username', 'user')

它工作正常,因为 userStore 从 localstorage 捕获这个项目并像它登录一样传递...但我不喜欢这个解决方案,看起来很脆弱,我想使用所做的操作对于登录用户。

我尝试的另一件事是在 window 中添加 app 变量,但它对我不起作用...不明白为什么...

main.js

视频显示代码:

const vue = new Vue({...})
if(window.Cypress){
  window.app = app
}

在我的例子中是:

const app = createApp(App)
if(window.Cypress){
  window.app = app
}

但是在 cypress 测试中 window.app 它是未定义的...我不知道如何使用它访问 userStore...就像它是 vuex。

这可能取决于商店的设置方式。

在 Pinia 演示应用程序中,商店在 App.vue 中初始化,所以这是我添加 Cypress 使用的引用的地方

export default defineComponent({
  components: { Layout, PiniaLogo },

  setup() {
    const user = useUserStore()
    const cart = useCartStore()
    if (window.Cypress) {
      window.store = {user, cart)
    }
    ...

然后在测试中(使用提供的main.spec.js

let store;

describe('Pinia demo with counters', () => {
  beforeEach(() => {
    cy.viewport(1000, 1000)
    cy.visit(`http://localhost:${PORT}`).then(win => store = win.store)
  })

  it('works', () => {
    cy.wait(500) // wait for the JS to load
      .then(() => store.cart.addItem('Cypress test item'))  // invoke action
      .then(() => {
        const item1 = store.cart.items[0]                   // invoke getter
        cy.wrap(item1)
          .should('have.property', 'name', 'Cypress test item')  // passes
      })

登录操作是异步的,所以我想您可能需要return允许赛普拉斯等待的承诺。

// user.js

async login(user, password) {
  const userData = await apiLogin(user, password)

  this.$patch({
    name: user,
    ...userData,
  })
  return userData   // this returns a promise which can awaited
},
// main.spec.js

describe('Pinia demo with counters', () => {
  beforeEach(() => {
    cy.viewport(1000, 1000)
    cy.visit(`http://localhost:${PORT}`).then(win => {
      store = win.store

      // default name in store before login
      cy.wrap(store.user.name).should('eq', 'Eduardo')

      // logging in
      store.user.login('ed', 'ed').then(() => {
        cy.wrap(store.user.name).should('eq', 'ed')
      })
    })
  })

或者,等待页面上的名称更改

// main.spec.js

cy.visit(`http://localhost:${PORT}`).then(win => {
  store = win.store

  // default name in store
  cy.wrap(store.user.name).should('eq', 'Eduardo')

  // loggin on
  store.user.login('ed', 'ed')  
  cy.contains('Hello ed')              // waits for name on page to change
    .then(() => {          
      cy.wrap(store.user.name).should('eq', 'ed')
    })
})

请注意,存储命令 运行 before 赛普拉斯命令在同一个块中,因此可能会在某些地方绊倒你。