运行 e2e 测试时在 cypress 中模拟特定的 graphql 请求

Posted

技术标签:

【中文标题】运行 e2e 测试时在 cypress 中模拟特定的 graphql 请求【英文标题】:Mock specific graphql request in cypress when running e2e tests 【发布时间】:2020-03-30 05:39:15 【问题描述】:

当使用Cypress 运行 e2e 测试时,我的目标是模拟特定的 graphql 查询。

目前,我可以像这样模拟所有请求:

cy.server();
cy.route('POST', '/graphql', 
    data: 
        foo: 'bar'
    ,
);

问题在于这会模拟 所有 /graphql 查询。如果我能以某种方式说,那就太棒了:

cy.route('POST', '/graphql', 'fooQuery', 
    data: 
        foo: 'bar'
    ,
);

在我们的应用程序中,我们使用的是 Apollo Graphql - 因此所有查询都被命名。

【问题讨论】:

在 cypress github 的 cmets 中发布了针对此问题的不同解决方法:github.com/cypress-io/cypress-documentation/issues/122。让我们知道哪一个对您有用 【参考方案1】:

在 cypress 6.0 中,routeroute2 已弃用,建议使用 intercept。正如文档 (https://docs.cypress.io/api/commands/intercept.html#Aliasing-individual-GraphQL-requests) 中所写,您可以通过以下方式模拟 GraphQL 请求:

cy.intercept('POST', '/api', (req) => 
  if (req.body.operationName === 'operationName') 
    req.reply( fixture: 'mockData.json');
  

【讨论】:

我们采用了intercept,这很棒 - 标记为正确答案。 @roberto 尝试了拦截功能,我的 test.json 文件包含从 Apollo 客户端查询返回的数据。获得以下未捕获的异常:“未捕获的 CypressError:以下错误源自您的测试代码,而不是来自 Cypress。> 传递给 cy.intercept() 的请求回调在拦截请求时引发错误:位置 1 处 JSON 中的意外令牌 o” @SuperMario,检查 JSON 文件是否有错误字符。 那里好像进入了无限循环。它尝试从夹具加载数据,然后再次重试,没有任何错误。【参考方案2】:

一种解决方法是在一个夹具文件中为相关的 graphql 操作提供模拟数据

cypress/support/commands.js

Cypress.Commands.add('stubGraphQL', (graphQlFixture) => 
  cy.fixture(graphQlFixture).then((mockedData) => 
    cy.on('window:before:load', (win) => 
      function fetch(path,  body ) 
        const  operationName  = JSON.parse(body)
        return responseStub(mockedData[operationName])
      
      cy.stub(win, 'fetch', fetch).withArgs("/graphql").as('graphql');
    );
  )
)


const responseStub = result => Promise.resolve(
  json: () => Promise.resolve(result),
  text: () => Promise.resolve(JSON.stringify(result)),
  ok: true,
)
//TODO how to get it to stop listening and trying to stub once the list of operations provided in fixture have been stubbed?

example fixture file cypress/fixtures/signInOperation.json(请注意,其中有 2 个操作,这就是您可以指定要模拟的响应的方式)


  "SIGNIN_MUTATION": 
    "data":"signin":"id":"ck896k87jac8w09343gs9bl5h","email":"sams@automation.com","name":"Sam","__typename":"User"
  ,
  "CURRENT_USER_QUERY" : 
    "data":"me":"id":"ck896k87jac8w09343gs9bl5h","email":"sams@automation.com","name":"!!Sam's Mock","permissions":["USER"],"cart":["id":"ck89gebgvse9w0981bhh4a147","quantity":5,"item":"id":"ck896py6sacox0934lqc8c4bx","price":62022,"image":"https://res.cloudinary.com/deadrobot/image/upload/v1585253000/sickfitz/ecgqu4i1wgcj41pdlbty.jpg","title":"MensShoes","description":"Men's Shoes","__typename":"Item","__typename":"CartItem","id":"ck89gec6mb3ei0934lmyxne52","quantity":5,"item":"id":"ck896os7oacl90934xczopgfa","price":70052,"image":"https://res.cloudinary.com/deadrobot/image/upload/v1585252932/sickfitz/i7ac6fqhsebxpmnyd2ui.jpg","title":"WomensShoes2","description":"Women's Shoes","__typename":"Item","__typename":"CartItem","id":"ck89gl45psely0981b2bvk6q5","quantity":7,"item":"id":"ck89ghqkpb3ng0934l67rzjxk","price":100000,"image":"https://res.cloudinary.com/deadrobot/image/upload/v1585269417/sickfitz/eecjz883y7ucshlwvsbw.jpg","title":"watch","description":"Fancy Watch","__typename":"Item","__typename":"CartItem"],"__typename":"User"
  

在你的规范文件中

cy.stubGraphQL('signInOperation.json')
cy.visit(yourURL)
cy.get(loginButton).click()

【讨论】:

【参考方案3】:

在 cypress 5.1 中,使用新的 route2 命令可以非常简单地模拟 GraphQL 请求,例如:

cy.route2('/graphql', (req) => 
  if(req.body.includes('operationName'))
    req.reply( fixture: 'mockData.json');
  
);

我刚刚添加了一个 if 条件来评估 GraphQL 请求的主体是否包含某个字符串作为查询的一部分。 如果这是真的,那么我会回复一个从夹具加载的自定义主体。

cy.route2() 的文档: https://docs.cypress.io/api/commands/route2.html

【讨论】:

非常感谢您提供这些信息?【参考方案4】:

如果你想使用fixture来响应graphql,你可以试试这个:

cy.intercept('POST', '/test_api/graphql', (req) => 
      req.continue((res) => 
        if (req.body.operationName === 'op_name') 
          res.send( fixture: 'MyFixture/xyz.json' ),
            req.alias = 'graphql'
        
      )
)

【讨论】:

以上是关于运行 e2e 测试时在 cypress 中模拟特定的 graphql 请求的主要内容,如果未能解决你的问题,请参考以下文章

ReactJS + Cypress E2E 测试

如何对接 NX cypress e2e 应用程序

Vue Cypress 和 Gitlab CI/CD

cypress初探

cypress初探

cypress初探