cypress route 拦截 zepto ajax 请求时候 response 返回 null 问题原因

如果你项目有如下几个巧合,大概率会发现一个 ajax 请求返回为 null 的 bug:

  1. 如果你的项目是移动端项目,刚好使用了 zepto.js
  1. 还刚好使用了 $.ajax 发送 ajax 请求。
  1. 刚好又使用了 cy.route

问题代码

src/index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
test:<div id="demo"></div>
<!-- 使用 jquery ajax 请求正常 -->
<!-- <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script> -->
<script src="https://cdn.bootcdn.net/ajax/libs/zepto/1.2.0/zepto.js"></script>
<script>
$.ajax({
type: "GET",
url: "/testCyPress",
data: {
content: 'test',
f: 'json'
},
dataType: "json",
success: function (response) {
$('#demo').html(JSON.stringify(response));
}
});
</script>
</body>
</html>

/cypress/integration/ajax.spec.js

1
2
3
4
5
6
7
8
9
10
11
12
13
/// <reference types="cypress" />

describe('Test', function() {
it('ajax', function() {
cy.viewport('iphone-6');

cy.route('GET', '**/testCyPress*', {"code":"111111","info":"成功"}).as('apiCheck')

cy.visit('http://localhost:8080/src/index.html')

cy.wait('@apiCheck')
})
})

以上代码理想情况:

不论后端接口返回任何数据,在 CyPress 测试中,相关 **/testCyPress* 接口都应该会返回 {"code":"111111","info":"成功"}

理想很丰满,现实很骨感

实际效果:

不会返回后端接口数据,也不会返回 {"code":"111111","info":"成功"},而是返回 null。

如果将 zepto 换成 jquery ,代码会如期运行!各种扒源码之后,发现了问题所在。

问题原因

对比 network 请求会发现少了好几个字段,少的字段如下:

1
2
3
4
5
X-Cypress-Delay: 0
X-Cypress-Id: xhr10
X-Cypress-Matched: **/testCyPress*
X-Cypress-Response: %7B%22code%22:%22111111%22,%22info%22:%22%E6%88%90%E5%8A%9F%22%7D
X-Cypress-Status: 200

查看 zepto ajax 源码 会发现有这么一行代码

https://github.com/madrobby/zepto/blob/master/src/ajax.js#L254

zepto.ajaxgithub
1
xhr.setRequestHeader = setHeader // xhr = new window.XMLHttpRequest()

就这么一行代码,改变了 XMLHttpRequest 的默认的 setRequestHeader 方法,导致 CyPress 测试请求发送的 Request Headers 少了好几个字段,进而导致返回数据为 null

处理办法

查看了所有 zepto 源码,并没有发现 xhr.setRequestHeader = setHeader 这行代码作用,唯一能想到的用处是:拦截浏览器 console 执行 ajax 请求,禁止携带 Request Headers

结合项目需求,可以删除这行代码。即可解决 response 返回 null 问题。

文章完。

本文由 linx(544819896@qq.com) 创作,采用 CC BY 4.0 CN协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。本文链接为: https://blog.jijian.link/2020-08-03/cypress-zepto-ajax-response-null/

如果您觉得文章不错,可以点击文章中的广告支持一下!