我一直在尝试使用cypress.io
测试条带结帐表单如果有人设法让这个工作,请告诉我。我在这里找到了一个关于这个问题的帖子https://github.com/cypress-io/cypress/issues/136,基于此,我提出了:
cy.get('iframe.stripe_checkout_app')
.wait(10000)
.then($iframe => {
const iframe = $iframe.contents()
const myInput0 = iframe.find('input:eq(0)')
const myInput1 = iframe.find('input:eq(1)')
const myInput2 = iframe.find('input:eq(2)')
const myButton = iframe.find('button')
cy
.wrap(myInput0)
.invoke('val', 4000056655665556)
.trigger('change')
cy
.wrap(myInput1)
.invoke('val', 112019)
.trigger('change')
cy
.wrap(myInput2)
.invoke('val', 424)
.trigger('change')
cy.wrap(myButton).click({ force: true })
})
但问题是条带形式仍未注册输入值。这是http://www.giphy.com/gifs/xT0xeEZ8CmCTVMwOU8发生的一点点GIF。基本上,表单不会注册更改输入触发器。
有没有人知道如何使用cypress将数据输入到iframe中的表单中?
答案 0 :(得分:9)
以下代码段应该对您有用。我从@izaacdb在this thread中的帖子中复制/粘贴了它。
cy.wait(5000)
cy.get('.__PrivateStripeElement > iframe').then($element => {
const $body = $element.contents().find('body')
let stripe = cy.wrap($body)
stripe.find('.Input .InputElement').eq(0).click().type('4242424242424242')
stripe = cy.wrap($body)
stripe.find('.Input .InputElement').eq(1).click().type('4242')
stripe = cy.wrap($body)
stripe.find('.Input .InputElement').eq(2).click().type('424')
})
但是,为了使以上各项起作用,您需要执行以下操作(从与上面链接的同一线程的@nerdmax帖子中复制/粘贴):
非常感谢@Vedelopment @ brian-mann!
我使用react-stripe-checkout组件进行了测试,并且可以正常工作。
只需添加一些解决方案详细信息,这样便可以节省其他时间。
chromeWebSecurity disable
:// cypress.json { "chromeWebSecurity": false }
--disable-site-isolation-trials
:检查:https://docs.cypress.io/api/plugins/browser-launch-api.html# 和#1951
// /plugins/index.js module.exports = (on, config) => { on("before:browser:launch", (browser = {}, args) => { if (browser.name === "chrome") { args.push("--disable-site-isolation-trials"); return args; } }); };
答案 1 :(得分:3)
此link中的解决方案对我有用。基本上,步骤如下:
答案 2 :(得分:1)
iframe工作流程仍然非常笨重(直到this feature实施)。现在,您可以尝试强制几乎每个DOM交互:
cy.visit("https://jsfiddle.net/1w9jpnxo/1/");
cy.get("iframe").then( $iframe => {
const $doc = $iframe.contents();
cy.wrap( $doc.find("#input") ).type( "test", { force: true });
cy.wrap( $doc.find("#submit") ).click({ force: true });
});
答案 3 :(得分:1)
我花了太长时间试图使它正常工作,我发现的答案都无法完全起作用。我将解决方案添加到了针对iframe的赛普拉斯github issue上(那里还有更多内容),也希望将其放到这里以节省其他时间。
我从this stackoverflow answer窃取了onIframeReady()函数。
基本上,这是检查iframe是否已加载,如果iframe已加载,它将执行$iframe.contents().find("body");
来切换到内容。如果尚未加载,它将把相同的代码挂接到load
事件中,因此它将在iframe加载后立即运行。
这是作为自定义命令编写的,以允许在切换到iframe后使用赛普拉斯链接,因此请将以下内容放入您的support/commands.js
文件中:
Cypress.Commands.add("iframe", { prevSubject: "element" }, $iframe => {
Cypress.log({
name: "iframe",
consoleProps() {
return {
iframe: $iframe,
};
},
});
return new Cypress.Promise(resolve => {
onIframeReady(
$iframe,
() => {
resolve($iframe.contents().find("body"));
},
() => {
$iframe.on("load", () => {
resolve($iframe.contents().find("body"));
});
}
);
});
});
function onIframeReady($iframe, successFn, errorFn) {
try {
const iCon = $iframe.first()[0].contentWindow,
bl = "about:blank",
compl = "complete";
const callCallback = () => {
try {
const $con = $iframe.contents();
if ($con.length === 0) {
// https://git.io/vV8yU
throw new Error("iframe inaccessible");
}
successFn($con);
} catch (e) {
// accessing contents failed
errorFn();
}
};
const observeOnload = () => {
$iframe.on("load.jqueryMark", () => {
try {
const src = $iframe.attr("src").trim(),
href = iCon.location.href;
if (href !== bl || src === bl || src === "") {
$iframe.off("load.jqueryMark");
callCallback();
}
} catch (e) {
errorFn();
}
});
};
if (iCon.document.readyState === compl) {
const src = $iframe.attr("src").trim(),
href = iCon.location.href;
if (href === bl && src !== bl && src !== "") {
observeOnload();
} else {
callCallback();
}
} else {
observeOnload();
}
} catch (e) {
// accessing contentWindow failed
errorFn();
}
}
然后您将在测试中这样称呼它:
cy.get('iframe.stripe_checkout_app')
.iframe()
.find('input:eq(0)')
.type("4000056655665556")
您可以在调用.iframe()
后再.alias()进行其余输入或.get()
iframe多次引用,我将由您自己决定。
答案 4 :(得分:1)
@ user8888的input
选择器对我不起作用。相反,我通过其name
属性访问每个 cy.get(".__PrivateStripeElement > iframe").then(($element) => {
const $body = $element.contents().find("body");
let stripe = cy.wrap($body);
stripe
.find('[name="cardnumber"]')
.click()
.type(MOCK_CC_NUMBER);
stripe = cy.wrap($body);
stripe
.find('[name="exp-date"]')
.click()
.type(MOCK_CC_EXP);
stripe = cy.wrap($body);
stripe
.find('[name="cvc"]')
.click()
.type(MOCK_CC_CVC);
stripe = cy.wrap($body);
stripe
.find('[name="postal"]')
.click()
.type(MOCK_CC_ZIP);
});
。
merge = concatenate([sent_encoder, USE], axis=-1)
答案 5 :(得分:0)
这并没有直接回答你的问题,但经过几天尝试使用jQuery在iframe中操纵元素后,重新实现赛普拉斯已经做过的一堆事情,我打了我自己,开始这样做:
Cypress.Commands.add('openiframe', () => {
return cy.get("iframe[src^='/']").then(iframe => {
cy.visit(Cypress.$(iframe).attr('src'), { timeout: Cypress.config("pageLoadTimeout") });
});
});
这让我只能使用cy.openiframe()。then(()=> {});并且好像我正在测试的网站没有在iframe中放置一堆功能。
缺点是,在iframe中执行任何操作之前,您必须完成不在iframe 中的操作,因此您无法返回太容易了。
它可能不适用于您的用例,但如果/当它用,它是我找到的最简单的解决方法。
答案 6 :(得分:0)
为了避免使用:
cy.wait(5000)
我找到了一种更好的方法,可以按照cypress在本教程中提供的有关how to work with iframes的说明进行操作
cy.get('iframe[name="__privateStripeFrame5"]')
.its("0.contentDocument.body")
.should("not.be.empty")
.then((body) => {
cy.wrap(body)
.find("[name=cardnumber]")
.type("6011111111111117", { force: true });
});