Cypress跨域限制问题:如何访问iframe内元素?
跨域iframe元素访问问题求助
测试网站时遇到跨域限制问题:被测网站包含一个iframe,其src属性指向与主站不同的源。该iframe的响应头已设置Access-Control-Allow-Origin: *。
网站HTML结构
<html> <head></head> <body> <a data-test-id="skip-to-content"> <span class="css-40g50j">Skip to main content</span> </a> <iframe title="Automation" sandbox="allow-same-origin" src="https://testDev.com/qa"> #document (https://testDev.com/qa#test) <!DOCTYPE html> <html lang="en"> <head></head> <body> <select id="test-selection"> <option value="test1" data-test-id="test1">Test 1</option> <option value="test2" data-test-id="test2">Test 2</option> </select> </body> </html> </iframe> </body> </html>
我尝试了多种方法访问iframe内的元素,但均未成功:
方案1:关闭Chrome Web安全
在cypress.config.ts中设置chromeWebSecurity: false,但网站需要web安全才能完成登录流程,此方案不可行。
方案2:自定义getIframe命令
命令代码:
Cypress.Commands.add('getIframe', (selector: string) => { return cy.get(selector) .its('0.contentDocument.body') .should('not.be.empty') .then(cy.wrap) }); describe('Test iframe', () => { it('Test iframe: ', () => { cy.visit("https://dev123.app.com"); cy.get('iframe[title="Automation"]').should('be.visible'); cy.getIframe('iframe[title="Automation"]').find('#test-selection').should('be.visible'); }); });
报错信息:
its.0.contentDocument.body CypressError Timed out retrying after 10000ms: cy.its() errored because the property: 0.contentDocument.body does not exist on your subject. cy.its() waited for the specified property 0.contentDocument.body to exist, but it never did. If you do not expect the property 0.contentDocument.body to exist, then add an assertion such as: cy.wrap({ foo: 'bar' }).its('quux').should('not.exist')Learn more _lib/support/commands.ts:20:1 18 | Cypress.Commands.add('getIframe', function (selector) { 19 | return cy.get(selector) > 20 | .its('0.contentDocument.body') | ^ 21 | .should('not.be.empty') 22 | .then(cy.wrap); 23 | });
方案3:使用cypress-iframe插件
步骤:
- 安装:
npm install -D cypress-iframe - 导入:
import 'cypress-iframe';
测试代码:
it('Test iframe: ', () => { cy.visit("https://dev123.app.com"); cy.frameLoaded('iframe[title="Automation"]'); cy.iframe().find('#test-selection').should('be.visible'); });
报错信息:
25 then{timeout: 30000}, function(){} SecurityError Failed to read a named property 'toString' from 'Location': Blocked a frame with origin "https://dev123.app.com" from accessing a cross-origin frame. node_modules/cypress-iframe/dist/index.js:97:41 95 | : (_a = fullOpts.url) === null || _a === void 0 ? void 0 : _a.test(contentWindow.location.toString()); 96 | } > 97 | : function () { return contentWindow.location.toString() !== 'about:blank'; }; | ^ 98 | _c.label = 1; 99 | case 1: 100 | if (!!hasNavigated()) return [3, 3];
方案4:使用cy.origin命令
测试代码:
it('Test iframe: ', () => { cy.visit("https://dev123.app.com"); cy.origin('https://testDev.com/qa', () => { cy.get('iframe[title="Automation"]').its('0.contentWindow.document').should('exist') .then((doc) => { cy.wrap(doc).find('#test-selection').should('be.visible'); }); }); });
报错信息:
24 originhttps://testDev.com 25 getiframe[title="Automation"] CypressError Timed out retrying after 10000ms: The command was expected to run against origin https://testDev.com but the application is at origin https://dev123.app.com. This commonly happens when you have either not navigated to the expected origin or have navigated away unexpectedly. Using cy.origin() to wrap the commands run on https://dev123.app.com will likely fix this issue. cy.origin('https://dev123.app.com', () => { <commands targeting https://dev123.app.com go here> })Learn more e2e/test.spec.ts:37:1 35 | // }); 36 | // cy.getIframe('iframe[title="Automation"]').find('#test-selection').should('be.visible'); > 37 | cy.origin('https://testDev.com', function () { | ^ 38 | cy.get('iframe[title="Automation"]').its('0.contentWindow.document').should('exist') 39 | .then(function (doc) { 40 | cy.wrap(doc).find('#test-selection').should('be.visible'); View stack trace
请问该如何解决这类问题?非常感谢!
内容的提问来源于stack exchange,提问作者Khanh Do
相关产品推荐
相关产品推荐

