在使用Cypress运行GraphQL应用时遇到了困难

我们正在开发一个采用了GraphQL的系统,并且使用Cypress进行端到端测试。然而,由于遇到了一些困难,所以我想为那些面临同样问题的人留下一些记录。

无法使用wait等待GraphQL请求。

如果/graphql是终结点的话,我认为可以这样写。

// 動かない
cy.server()
cy.route('POST', '/graphql').as('graphql')
cy.wait('@graphql')

然而,如果继续这样下去,他不会等待。

根据目前(2019/02/07)的情况看,Cypress尚未支持fetch API,这似乎是发生的原因。

计划提供支持:https://github.com/cypress-io/cypress/issues/687

因此,对于像Apollo Client这样的情况,它内部似乎使用了fetch API,在上面的代码中不起作用。

据说可以使用 delete 操作符将 fetch 删除并返回至 XMLHttpRequest API,作为解决方案。

需要在index.js等文件中执行以下操作。

// index.js
Cypress.on('window:before:load', (win) => {
    delete win.fetch
})

请参考以下链接:https://github.com/cypress-io/cypress-example-recipes/tree/master/examples/stubbing-spying__window-fetch

由于只有一个终端节点,无法为每个请求创建别名。

這可以說是一個絆腳石,或者說是一個令人擔心的事情。

如果在一次测试中进行多个请求,GraphQL允许只有一个终点(例如/graphql),

不能为每个请求设定不同的别名。

// リクエストが全て同じエンドポイント
cy.route('POST', '/graphql').as('query1')
cy.route('POST', '/graphql').as('query2')

这不是关于解决方案之类的问题,

其中之一是 GraphQL 的特點

因为在一个请求中可以获取到所需的所有数据,所以

理论上不应该出现在同一时间进行多次请求的情况。

在那里应该有一个必须的流,对于GraphQL,即使端点相同,也应该总是能够确定是在请求哪个查询。

cy.server()
// ログイン
cy.route('POST', '/graphql').as('loginMutation')
cy.get('input').eq(0).type('taro@example.com')
cy.get('input').eq(1).type('password1234')
cy.get('button').click()
cy.wait('@loginMutation')
// ログイン後一覧データ取得
cy.route('POST', '/graphql').as('postsQuery') // 同じエンドポイントだがこのタイミングでは必ず一度だけリクエストが行われる
cy.wait('@postsQuery')

如果必须在相同的时间内发生多个请求并需要给它们起别名,只能自己制作一个命令,以body中的数据来进行判定。

请参考以下链接,了解如何在Cypress中为特定的GraphQL请求进行别名设置:https://stackoverflow.com/questions/53814647/how-can-i-alias-specific-graphql-requests-in-cypress

每次测试时,localStorage都不会被缓存

我想在GraphQL中使用基于令牌的认证,例如JWT。

在这种情况下,应该将令牌存储在本地存储中,并将其放入授权头中进行请求。

由于Cypress每次测试后都会清除localStorage,因此无法保持登录状态。

因此,在beforeEach()中每次执行登录处理,导致测试的执行时间变得冗长而浪费。

在Cookie的情况下,您可以将希望保留的数据添加到Cypress的白名单中。

因为在localStorage的情况下没有提供这样的API,所以需要使用一种解决方法。

// index.js

// 保持するトークン
let token

// トークンをlocalStorageにセット
const setToken = () => {
  if (token) {
    localStorage.setItem('token', token)
  }
}

// トークンをキャッシュ
const cacheToken = () => {
  token = localStorage.getItem('token')
}

// テスト実行前にトークンをセット
beforeEach(setToken)

// テスト実行後にトークンをキャッシュ
afterEach(cacheToken)

通过这样做,只要在before()函数中插入一次登录处理,之后的所有测试就可以在保持登录状态的情况下进行执行。

请参考以下链接:https://github.com/cypress-io/cypress/issues/461

最终

在使用Cypress来运行GraphQL应用程序时,我介绍了我遇到的困难。

如果还有其他方法,比如说”还有一种好的解决方式”、”遇到这个问题时我这样解决了”之类的,请务必告诉我。

广告
将在 10 秒后关闭
bannerAds