Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Selenium在条带信用卡输入中发送密钥顺序不正确_Selenium_Google Chrome_Selenium Chromedriver_Stripe Payments - Fatal编程技术网

Selenium在条带信用卡输入中发送密钥顺序不正确

Selenium在条带信用卡输入中发送密钥顺序不正确,selenium,google-chrome,selenium-chromedriver,stripe-payments,Selenium,Google Chrome,Selenium Chromedriver,Stripe Payments,使用selenium将键发送到输入字段后,结果与预期不符-键的插入顺序不正确 e、 g.发送密钥('42424242')->结果为“42242424” 编辑:在一些机器上,我只是随机观察问题,10次尝试中有1次。在另一台机器上是10/10 这种情况在Stripe payment form+中特别发生,我只在Chrome版本69中看到这个问题(在以前的版本中,它工作正常) 这可以很容易地在样本条站点上复制: python代码示例: from selenium import webdriver dr

使用selenium将键发送到输入字段后,结果与预期不符-键的插入顺序不正确

e、 g.发送密钥('42424242')->结果为“42242424”

编辑:在一些机器上,我只是随机观察问题,10次尝试中有1次。在另一台机器上是10/10

这种情况在Stripe payment form+中特别发生,我只在Chrome版本69中看到这个问题(在以前的版本中,它工作正常)

这可以很容易地在样本条站点上复制:

python代码示例:

from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://stripe.github.io/elements-examples/')
driver.switch_to.frame(driver.find_element_by_tag_name('iframe'))  # First iframe
cc_input = driver.find_element_by_css_selector('input[name="cardnumber"]')
cc_input.send_keys('4242424242424242')
结果:

我可以通过一个接一个地发送钥匙来获得通过,但这也不是100%可靠(加上非常慢)

我不确定这是硒(3.14.1)/chromedriver(2.41.578737)的问题,还是我做错了什么

有什么想法吗?

编辑

非常感谢@Benno——他的回答是正确的。 我将添加基于他的JS为我工作的python解决方案

driver.get('https://stripe.github.io/elements-examples/')
driver.switch_to.frame(driver.find_element_by_tag_name('iframe'))  # First iframe
cc_input = driver.find_element_by_css_selector('input[name="cardnumber"]')
value = "4242424242424242"
driver.execute_script('''
 input = arguments[0];
 var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set; 
 nativeInputValueSetter.call(input, "{}");
 var eventCard = new Event("input", {{bubbles: true}});
 input.dispatchEvent(eventCard);
 '''.format(value), cc_input)
driver.switch_to.default_content()
driver.quit()
经过几个小时的尝试,我放弃了,接受了这个事实,这确实是一个随机的问题,并采取了解决办法

  • 在不需要更新的地方,我将使用<69的Chrome版本
  • 为了测试最新的Chrome,我将使用React溶液
  • 我的发现

    这个问题主要出现在MacOS上,很少出现在Windows上(很可能还有其他因素在起作用,这只是一个观察)

    我做了一个实验,重复填写表格100次

    Mac-68故障

    Windows-6次故障


    Cookie/本地历史(如评论中所示)似乎不是问题所在。webdriver总是生成一个“干净”的浏览器实例,没有Cookie或本地存储。

    我们在MacOS和Ubuntu 18.04上遇到了完全相同的问题,在我们的CI服务器上也遇到了同样的问题,该服务器具有Gractor 5.4.1和selenium和chromedriver的相同版本。自Chrome69之后,它才开始出现故障,v70的情况更糟

    更新-正在工作(暂时)

    经过进一步的调查,我记得React倾向于覆盖更改/输入事件,信用卡输入、ccv输入等中的值是从React组件状态呈现的,而不仅仅是从输入值呈现的。于是我开始寻找,发现

    我们的测试正在进行(目前):

    //信用输入示例
    函数creditCardInput():ElementFinder{
    返回元素(by.xpath('//input[contains(@name,“cardnumber”)]'))
    }
    /// ... 我们的方法的片段。。。
    等待重新编辑CardInputsReady()
    等待剥离输入(creditCardInput,ccNumber)
    等待剥离输入(信用卡到期,ccExpiry)
    等待剥离输入(信用卡CVC、ccCvc)
    wait browser.wait(this.hasCreditCardZip(),未定义,'Should has creditCardZip')
    等待剥离输入(creditCardZip、ccZip)
    等待browser.switchTo().defaultContent()
    /// ... 剪
    异步函数ensurectardinputisready():Promise{
    wait browser.wait(ExpectedConditions.presenceOf(paymentIFrame()),未定义,“应具有付款iframe”)
    wait browser.switchTo().frame(wait paymentIFrame().getWebElement())
    等等(
    ExpectedConditions.presenceOf(creditCardInput()),
    未定义,
    '应该有信用卡输入'
    )
    }
    /**
    *自版本69以来,条带网关的SendKeys在Chrome中出现问题。钥匙坏了,
    *导致测试失败。
    */
    异步函数stripeInput(inputElement:function,value:string):承诺{
    等待browser.executeScript(`
    var nativeInputValueSetter=Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,“value”).set;
    调用(参数[0],“${value}”);
    var-inputEvent=new事件('input',{bubbles:true});
    参数[0]。dispatchEvent(inputEvent);
    `,inputElement()
    )
    等待浏览器。睡眠(100)
    const typedInValue=await inputElement().getWebElement().getAttribute('value'))
    if(typedInValue.replace(/\s/g',)==值){
    返回
    }
    抛出新错误(${inputElement}`上的`失败集'${typedInValue}')
    }
    
    以前的想法(只是偶尔奏效):

    from selenium import webdriver
    driver = webdriver.Chrome()
    driver.get('https://stripe.github.io/elements-examples/')
    driver.switch_to.frame(driver.find_element_by_tag_name('iframe'))  # First iframe
    cc_input = driver.find_element_by_css_selector('input[name="cardnumber"]')
    cc_input.send_keys('4242424242424242')
    
    我已经使用设置了一个最小的repu,当测试按顺序运行时它会成功,但不是并行运行(我们认为这是由于切换到iframe时的焦点/模糊问题)

    我们的解决方案是类似的,尽管我们从观察测试中注意到input.clear()不适用于iframe中使用的tel输入

    这仍然是偶尔失败的,但频率要低得多

    /**
     * Types a value into an input field, and checks if the value of the input
     * matches the expected value. If not, it attempts for `maxAttempts` times to
     * type the value into the input again.
     *
     * This works around an issue with ChromeDriver where sendKeys() can send keys out of order,
     * so a string like "0260" gets typed as "0206" for example.
     *
     * It also works around an issue with IEDriver where sendKeys() can press the SHIFT key too soon
     * and cause letters or numbers to be converted to their SHIFT variants, "6" gets typed as "^", for example.
     */
    export async function slowlyTypeOutField (
      value: string,
      inputElement: Function,
      maxAttempts = 20
    ): Promise<void> {
      for (let attemptNumber = 0; attemptNumber < maxAttempts; attemptNumber++) {
        if (attemptNumber > 0) {
          await browser.sleep(100)
        }
    
        /*
          Executing a script seems to be a lot more reliable in setting these flaky fields than using the sendKeys built-in
          method. However, I struggled in finding out which JavaScript events Stripe listens to. So we send the last key to
          the input field to trigger all events we need.
         */
        const firstPart = value.substring(0, value.length - 1)
        const secondPart = value.substring(value.length - 1, value.length)
        await browser.executeScript(`
            arguments[0].focus();
            arguments[0].value = "${firstPart}";
          `,
          inputElement()
        )
        await inputElement().sendKeys(secondPart)
        const typedInValue = await inputElement().getAttribute('value')
    
        if (typedInValue === value) {
          return
        }
    
        console.log(`Tried to set value ${value}, but instead set ${typedInValue} on ${inputElement}`)
      }
    
      throw new Error(`Failed after ${maxAttempts} attempts to set value on ${inputElement}`)
    }
    
    /**
    *在输入字段中键入值,并检查输入的值
    *与预期值匹配。如果没有,则尝试“maxAttempts”次以
    *再次在输入中键入值。
    *
    *这解决了ChromeDriver的一个问题,其中sendKeys()可以按顺序发送密钥,
    *例如,像“0260”这样的字符串被键入为“0206”。
    *
    *它还解决了IEDriver中sendKeys()可能过早按下SHIFT键的问题
    *并将字母或数字转换为其移位变量,例如,“6”被键入为“^”。
    */
    导出异步函数slowlyTypeOutField(
    值:字符串,
    inputElement:函数,
    最大尝试次数=20
    ):承诺{
    for(设attemptNumber=0;attemptNumber0){
    等待浏览器。睡眠(100)
    }
    /*
    在设置这些不稳定的字段时,执行脚本似乎比使用内置sendKeys要可靠得多
    然而,我很难找到Stripe侦听的JavaScript事件。因此,我们将最后一个键发送到
    用于触发我们需要的所有事件的输入字段。
    */
    const firstPart=value.substring(0,value.length-1)
    常数第二部分=
    
        input_data = "someimputdata"
        some_xpath = "//*[contains(@id,'input_fax.number_')]"
        element = web_driver_obj.find_element_by_xpath(some_xpath)
        element.clear()
        element.send_keys(input_data)
        web_driver_obj.execute_script("arguments[0].value = '{0}';".format(input_data), element)
    
    from selenium.webdriver.common.keys import Keys
    
    my_value = "123"
    my_xpath="//input[@class='form-text']"
    element = driver.find_element_by_xpath(my_xpath)
    element.clear()
    element.send_keys(Keys.BACKSPACE * 3, my_value)