无法拦截 Cypress API 调用
Can't intercept Cypress API call
我一直坚持使用 Cypress 固定装置。无法使用 SSR 和导航路由拦截 XHR 请求。
cypress/integration/page.js:
const fetch = require("unfetch")
describe("/about", () => {
beforeEach(() => {
cy.visit("/", { // Visit home page to trigger SSR
onBeforeLoad (win) {
win.fetch = fetch // replace fetch with xhr implementation
},
})
})
it("Has a correct title", () => {
cy.server()
cy.fixture("about").then(about => {
// about object is correct here, like {title: "About+"}
cy.route("GET", "http://localhost:8080/api/documents/url", about) // Not sure where .route should be
cy.get(".main > :nth-child(1) > a").click() // Navigate to the /about page
cy.route("GET", "http://localhost:8080/api/documents/url", about) // Tried both ways
// This hits my server API without stubbing, getting {title: "About"}
cy.title().should("eq", "About+") // About != About+
})
})
})
cypress/fixtures/about.json:
{"title": "About+"}
我在 Dev Tools 中看到一个 XHR 请求 (type=xhr),它没有使用上面的 about
存根对象,而是命中了真实的 API。为什么?仔细检查 URL 和方法——100% 相同。难道route
耦合到visit
而忽略了基于点击的路由?!
再次检查,我找到了解决办法。让我分享给大家感兴趣的细节:
1) 我使用 Next.js which is an excellent tool for SSR but it doesn't allow you to disable server-side rendering (yet) according to this and this 个问题。
2) 您可以将 Cypress 与 SSR 页面一起使用,但通过这种方式,您只能测试真实的 HTML。这意味着您必须将测试耦合到真实数据(在大多数情况下不好)或存根数据库本身(慢)。通常,您想存根 HTTP 请求。
3) Cypress 无法对 fetch
请求进行存根,并且使用基于 XHR 的实现模拟 fetch
比我想象的要棘手。
首先你需要:
// cypress/integration/your-test.js
Cypress.on('window:before:load', (win) => {
delete win.fetch
})
然后:
// pages/your-page.js
Entry.getInitialProps = async function() {
window.fetch = require("unfetch").default
...
}
我尝试的删除和更新代码行的其他组合没有产生积极的结果。例如,当我在测试文件中有 window.fetch =
行时它不起作用并且 fetch.toString()
给出了 "native code"
。不知道为什么,没有时间进一步探索。
Axios 解决了上述问题,但我不喜欢用额外的东西来膨胀我的包。您可以注入基于 XHR 的 fetch
仅用于测试。
4) 最重要的缺失部分。您需要等待路线。
it("Has a correct title", () => {
cy.visit("/")
cy.server()
cy.route("GET", "http://localhost:8080/api/documents/url/about", {title: "About+"}).as("about")
cy.get("[href='/about']").click()
cy.wait("@about") // !!!
cy.get("h1").contains("About+")
})
我一直坚持使用 Cypress 固定装置。无法使用 SSR 和导航路由拦截 XHR 请求。
cypress/integration/page.js:
const fetch = require("unfetch")
describe("/about", () => {
beforeEach(() => {
cy.visit("/", { // Visit home page to trigger SSR
onBeforeLoad (win) {
win.fetch = fetch // replace fetch with xhr implementation
},
})
})
it("Has a correct title", () => {
cy.server()
cy.fixture("about").then(about => {
// about object is correct here, like {title: "About+"}
cy.route("GET", "http://localhost:8080/api/documents/url", about) // Not sure where .route should be
cy.get(".main > :nth-child(1) > a").click() // Navigate to the /about page
cy.route("GET", "http://localhost:8080/api/documents/url", about) // Tried both ways
// This hits my server API without stubbing, getting {title: "About"}
cy.title().should("eq", "About+") // About != About+
})
})
})
cypress/fixtures/about.json:
{"title": "About+"}
我在 Dev Tools 中看到一个 XHR 请求 (type=xhr),它没有使用上面的 about
存根对象,而是命中了真实的 API。为什么?仔细检查 URL 和方法——100% 相同。难道route
耦合到visit
而忽略了基于点击的路由?!
再次检查,我找到了解决办法。让我分享给大家感兴趣的细节:
1) 我使用 Next.js which is an excellent tool for SSR but it doesn't allow you to disable server-side rendering (yet) according to this and this 个问题。
2) 您可以将 Cypress 与 SSR 页面一起使用,但通过这种方式,您只能测试真实的 HTML。这意味着您必须将测试耦合到真实数据(在大多数情况下不好)或存根数据库本身(慢)。通常,您想存根 HTTP 请求。
3) Cypress 无法对 fetch
请求进行存根,并且使用基于 XHR 的实现模拟 fetch
比我想象的要棘手。
首先你需要:
// cypress/integration/your-test.js
Cypress.on('window:before:load', (win) => {
delete win.fetch
})
然后:
// pages/your-page.js
Entry.getInitialProps = async function() {
window.fetch = require("unfetch").default
...
}
我尝试的删除和更新代码行的其他组合没有产生积极的结果。例如,当我在测试文件中有 window.fetch =
行时它不起作用并且 fetch.toString()
给出了 "native code"
。不知道为什么,没有时间进一步探索。
Axios 解决了上述问题,但我不喜欢用额外的东西来膨胀我的包。您可以注入基于 XHR 的 fetch
仅用于测试。
4) 最重要的缺失部分。您需要等待路线。
it("Has a correct title", () => {
cy.visit("/")
cy.server()
cy.route("GET", "http://localhost:8080/api/documents/url/about", {title: "About+"}).as("about")
cy.get("[href='/about']").click()
cy.wait("@about") // !!!
cy.get("h1").contains("About+")
})