Cypress 有一个 ... 使用 iframe 的困难。主要是因为所有内置的cy
DOM 遍历命令在它们#document
到达 iframe 内的节点时都会硬停止。
iframe 看到 Cypress 命令时(重新制定)
如果您的 Web 应用程序使用 iframe,则处理这些 iframe 中的元素需要您自己的自定义代码。在这篇博文中,我将展示如何与 iframe 内的 DOM 元素交互(即使 iframe 是从另一个域提供的),如何监视window.fetch
iframe 发出的请求,甚至如何存根来自 iframe 的 XHR 请求。
注意:您可以在存储库中的 “使用 iframes” 配方中找到此博客文章的源代码 cypress-example-recipes。
使用 iframe 的应用程序
让我们使用一个静态 HTML 页面并嵌入一个 iframe。这是完整的源代码。
<body>
<style>
iframe {
width: 90%;
height: 100%;
}
</style>
<h1>XHR in iframe</h1>
<iframe src="https://jsonplaceholder.cypress.io/"
data-cy="the-frame"></iframe>
</body>
提示:我们将按照选择元素指南的最佳实践使用data-cy
属性来查找 iframe 。
让我们在cypress/integration/first-spec.js
访问页面的规范文件中编写第一个测试。
it('gets the post', () => {
cy.visit('index.html').contains('XHR in iframe')
cy.get('iframe')
})
测试通过,我们可以看到加载的 iframe。
显示 iframe
如果我们手动单击 “尝试” 按钮,iframe 确实会获取第一篇文章。
当用户点击 “Try It” 按钮时,结果显示在下方
单击 iframe 内的按钮
让我们尝试编写测试命令以找到 “尝试” 按钮,然后单击它。该按钮位于body
元素document
的iframe
元素内。让我们编写一个辅助函数来获取body
元素。
const getIframeDocument = () => {
return cy
.get('iframe[data-cy="the-frame"]')
// Cypress yields jQuery element, which has the real
// DOM element under property "0".
// From the real DOM iframe element we can get
// the "document" element, it is stored in "contentDocument" property
// Cypress "its" command can access deep properties using dot notation
// https://on.cypress.io/its
.its('0.contentDocument').should('exist')
}
const getIframeBody = () => {
// get the document
return getIframeDocument()
// automatically retries until body is loaded
.its('body').should('not.be.undefined')
// wraps "body" DOM element to allow
// chaining more Cypress commands, like ".find(...)"
.then(cy.wrap)
}
it('gets the post', () => {
cy.visit('index.html')
getIframeBody().find('#run-button').should('have.text', 'Try it').click()
getIframeBody().find('#result').should('include.text', '"delectus aut autem"')
})
不幸的是,测试失败了 -contentDocument
元素永远不会从null
.
Cypress 测试无法访问 iframe 的文档
我们的问题是我们的测试在域下运行localhost
(您可以在浏览器的 url 中看到它),而按钮和 iframe 本身来自域jsonplaceholder.cypress.io
。浏览器不允许来自一个域的 JavaScript 访问另一个域中的元素——这将是一个巨大的安全漏洞。因此ÿ