How can I alias specific GraphQL requests in Cypress?

use*_*888 9 graphql cypress

In Cypress, it is well-documented that you can alias specific network requests, which you can then "wait" on. This is especially helpful if you want to do something in Cypress after a specific network request has fired and finished.

Example below from Cypress documentation:

cy.server()
cy.route('POST', '**/users').as('postUser') // ALIASING OCCURS HERE
cy.visit('/users')
cy.get('#first-name').type('Julius{enter}')
cy.wait('@postUser')
Run Code Online (Sandbox Code Playgroud)

However, since I'm using GraphQL in my app, aliasing no longer becomes a straightforward affair. This is because all GraphQL queries share one endpoint /graphql.

Despite it not being possible to differentiate between different graphQL queries using the url endpoint alone, it is possible to differentiate graphQL queries using operationName (refer to following image).

在此处输入图片说明

Having dug through the documentation, there doesn't appear to be a way to alias graphQL endpoints using operationName from the request body. I'm also returning the operationName (yellow arrow) as a custom property in my response header; however, I haven't managed to find a way to use it to alias specific graphQL queries either.

FAILED METHOD 1: This method attempts to use the purple arrow shown in image.

cy.server();
cy.route({
    method: 'POST',
    url: '/graphql',
    onResponse(reqObj) {
        if (reqObj.request.body.operationName === 'editIpo') {
            cy.wrap('editIpo').as('graphqlEditIpo');
        }
    },
});
cy.wait('@graphqlEditIpo');
Run Code Online (Sandbox Code Playgroud)

This method doesn't work since the graphqlEditIpo alias is registered at runtime and as such, the error I receive is as follows.

CypressError: cy.wait() could not find a registered alias for: '@graphqlEditIpo'. Available aliases are: 'ipoInitial, graphql'.

FAILED METHOD 2: This method attempts to use the yellow arrow shown in image.

cy.server();
cy.route({
    method: 'POST',
    url: '/graphql',
    headers: {
        'operation-name': 'editIpo',
    },
}).as('graphql');
cy.wait('graphql');
Run Code Online (Sandbox Code Playgroud)

此方法无效,因为cy.route的options对象中的headers属性实际上旨在接受每个docs存根路由的响应标头。在这里,我试图用它来识别我的特定graphQL查询,这显然行不通。

这就引出了我的问题:如何在赛普拉斯中为特定的graphQL查询/突变设置别名?我错过了什么吗?

Tra*_*oyd 8

intercept6.0.0 中引入的API 通过请求处理函数支持这一点。我在我的代码中使用它,如下所示:

cy.intercept('POST', '/graphql', req => {
  if (req.body.operationName === 'queryName') {
    req.alias = 'queryName';
  } else if (req.body.operationName === 'mutationName') {
    req.alias = 'mutationName';
  } else if (...) {
    ...
  }
});
Run Code Online (Sandbox Code Playgroud)

您的 GQL 操作的名称在哪里queryNamemutationName在哪里。您可以为要别名的每个请求添加附加条件。然后你可以像这样等待它们:

// Wait on single request
cy.wait('@mutationName');

// Wait on multiple requests. 
// Useful if several requests are fired at once, for example on page load. 
cy.wait(['@queryName, @mutationName',...]);
Run Code Online (Sandbox Code Playgroud)

文档在这里有一个类似的例子:https : //docs.cypress.io/api/commands/intercept.html#Aliasing-individual-requests


小智 5

这对我有用!

Cypress.Commands.add('waitForGraph', operationName => {
  const GRAPH_URL = '/api/v2/graph/';
  cy.route('POST', GRAPH_URL).as("graphqlRequest");
  //This will capture every request
  cy.wait('@graphqlRequest').then(({ request }) => {
    // If the captured request doesn't match the operation name of your query
    // it will wait again for the next one until it gets matched.
    if (request.body.operationName !== operationName) {
      return cy.waitForGraph(operationName)
    }
  })
})
Run Code Online (Sandbox Code Playgroud)

请记住尽可能使用唯一名称编写查询,因为操作名称依赖于它。


小智 4

如果“等待”而不是“别名”本身是主要目的,那么最简单的方法(正如我迄今为止遇到的那样)是对一般 graphql 请求进行别名,然后对“等待”目标进行递归函数调用新创建的别名,直到找到您正在寻找的特定 graphql 操作。例如

Cypress.Commands.add('waitFor', operationName => {
  cy.wait('@graphqlRequest').then(({ request }) => {
    if (request.body.operationName !== operationName) {
      return cy.waitFor(operationName)
    }
  })
})
Run Code Online (Sandbox Code Playgroud)

这当然有其注意事项,并且可能会也可能不会在您的环境中起作用。但这对我们有用。

我希望赛普拉斯将来能以一种不那么棘手的方式实现这一点。

附言。我想归功于我的灵感来源,但它似乎迷失在网络空间中。