代码之家  ›  专栏  ›  技术社区  ›  Kalle Richter

为什么我可以单击h:selectOneRadio的type=radio输入,而不是带有石墨烯/硒的p:selectOneRadio输入?

  •  4
  • Kalle Richter  · 技术社区  · 7 年前

    A. h:selectOneRadio 结果 <input type="radio"> 在一张桌子上 p:selectOneRadio 在里面 <输入类型=“收音机”> 在一张桌子上 div s在 input . 两者的id都是 [form id]:[selectOneRadio id]:[option number] 我可以在石墨烯功能测试中成功地将其用于普通JSF @FindBy(id="[...]") 而PrimeFaces变体由于以下原因而失败: org.openqa.selenium.ElementNotInteractableException . 调查生成的HTML,我看不出有什么不同

    <html xmlns="http://www.w3.org/1999/xhtml">
    
    <head>
      <link type="text/css" rel="stylesheet" href="/34696ceb-eeaa-4b35-88dd-f3c8fc5901bf/javax.faces.resource/theme.css.xhtml?ln=primefaces-aristo">
      <link type="text/css" rel="stylesheet" href="/34696ceb-eeaa-4b35-88dd-f3c8fc5901bf/javax.faces.resource/primefaces.css.xhtml;jsessionid=48ca919d0b7e89661f92149ac321?ln=primefaces&amp;v=5.0">
      <script type="text/javascript" src="/34696ceb-eeaa-4b35-88dd-f3c8fc5901bf/javax.faces.resource/jquery/jquery.js.xhtml;jsessionid=48ca919d0b7e89661f92149ac321?ln=primefaces&amp;v=5.0"></script>
      <script type="text/javascript" src="/34696ceb-eeaa-4b35-88dd-f3c8fc5901bf/javax.faces.resource/primefaces.js.xhtml;jsessionid=48ca919d0b7e89661f92149ac321?ln=primefaces&amp;v=5.0"></script>
      <title>Facelet Title</title>
    </head>
    
    <body>
      <form id="mainForm" name="mainForm" method="post" action="/34696ceb-eeaa-4b35-88dd-f3c8fc5901bf/index.xhtml;jsessionid=48ca919d0b7e89661f92149ac321" enctype="application/x-www-form-urlencoded">
        <input name="mainForm" value="mainForm" type="hidden">
        <table id="mainForm:mainSelectOneRadio">
          <tbody>
            <tr>
              <td>
                <input name="mainForm:mainSelectOneRadio" id="mainForm:mainSelectOneRadio:0" value="a" type="radio">
                <label for="mainForm:mainSelectOneRadio:0"> a</label>
              </td>
              <td>
                <input name="mainForm:mainSelectOneRadio" id="mainForm:mainSelectOneRadio:1" value="b" type="radio">
                <label for="mainForm:mainSelectOneRadio:1"> b</label>
              </td>
              <td>
                <input name="mainForm:mainSelectOneRadio" id="mainForm:mainSelectOneRadio:2" value="c" type="radio">
                <label for="mainForm:mainSelectOneRadio:2"> c</label>
              </td>
            </tr>
          </tbody>
        </table>
        <table id="mainForm:mainSelectOneRadioPrime" class="ui-selectoneradio ui-widget">
          <tbody>
            <tr>
              <td>
                <div class="ui-radiobutton ui-widget">
                  <div class="ui-helper-hidden-accessible">
                    <input id="mainForm:mainSelectOneRadioPrime:0" name="mainForm:mainSelectOneRadioPrime" value="aPrime" type="radio">
                  </div>
                  <div class="ui-radiobutton-box ui-widget ui-corner-all ui-state-default"><span class="ui-radiobutton-icon ui-icon ui-icon-blank"></span>
                  </div>
                </div>
              </td>
              <td>
                <label for="mainForm:mainSelectOneRadioPrime:0">aPrime</label>
              </td>
              <td>
                <div class="ui-radiobutton ui-widget">
                  <div class="ui-helper-hidden-accessible">
                    <input id="mainForm:mainSelectOneRadioPrime:1" name="mainForm:mainSelectOneRadioPrime" value="bPrime" type="radio">
                  </div>
                  <div class="ui-radiobutton-box ui-widget ui-corner-all ui-state-default"><span class="ui-radiobutton-icon ui-icon ui-icon-blank"></span>
                  </div>
                </div>
              </td>
              <td>
                <label for="mainForm:mainSelectOneRadioPrime:1">bPrime</label>
              </td>
              <td>
                <div class="ui-radiobutton ui-widget">
                  <div class="ui-helper-hidden-accessible">
                    <input id="mainForm:mainSelectOneRadioPrime:2" name="mainForm:mainSelectOneRadioPrime" value="cPrime" type="radio">
                  </div>
                  <div class="ui-radiobutton-box ui-widget ui-corner-all ui-state-default"><span class="ui-radiobutton-icon ui-icon ui-icon-blank"></span>
                  </div>
                </div>
              </td>
              <td>
                <label for="mainForm:mainSelectOneRadioPrime:2">cPrime</label>
              </td>
            </tr>
          </tbody>
        </table>
        <input name="javax.faces.ViewState" id="j_id1:javax.faces.ViewState:0" value="-485558793831512050:990657069126697889" autocomplete="off" type="hidden">
      </form>
    </body>
    
    </html>
    

    如果我将应用程序部署在Payara 4.1.2或任何其他原因上 ElementNotInteractableException .

    @RunWith(Arquillian.class)
    public class MyManagedBeanTest {
        private static final String WEBAPP_SRC = "src/main/webapp";
        private final static Logger LOGGER = LoggerFactory.getLogger(MyManagedBeanTest.class);
    
        @Deployment(testable = false)
        public static Archive<?> createDeployment0() throws TransformerException, XPathExpressionException, ParserConfigurationException, SAXException, IOException {
            WebArchive retValue = ShrinkWrap.create(WebArchive.class)
                    .add(EmptyAsset.INSTANCE, "beans.xml")
                    .addClasses(MyManagedBean.class)
                    .addAsWebInfResource(
                            new StringAsset("<faces-config version=\"2.0\"/>"),
                            "faces-config.xml");
            Maven.configureResolver().workOffline().resolve("richtercloud:graphene-click-input-radio:war:1.0-SNAPSHOT").withoutTransitivity().asList(JavaArchive.class).forEach(dependency -> retValue.addAsLibrary(dependency));
            //add all webapp resources
            retValue.merge(ShrinkWrap.create(GenericArchive.class)
                    .as(ExplodedImporter.class)
                    .importDirectory(WEBAPP_SRC)
                    .as(GenericArchive.class), "/", Filters.include(".*\\.(xhtml|css|js|png)$"));
    
            ByteArrayOutputStream archiveContentOutputStream = new ByteArrayOutputStream();
            retValue.writeTo(archiveContentOutputStream, Formatters.VERBOSE);
            LOGGER.info(archiveContentOutputStream.toString());
            return retValue;
        }
    
        @Drone
        private WebDriver browser;
        @ArquillianResource
        private URL deploymentUrl;
        @FindBy(id = "mainForm:mainSelectOneRadio:0")
        private WebElement mainSelectOneRadioOption0;
        @FindBy(id = "mainForm:mainSelectOneRadioPrime:0")
        private WebElement mainSelectOneRadioPrimeOption0;
    
        @Test
        public void testAll() {
            browser.get(deploymentUrl.toExternalForm()+"index.xhtml");
            LOGGER.debug(browser.getPageSource());
            mainSelectOneRadioOption0.click();
            mainSelectOneRadioPrimeOption0.click();
        }
    }
    

    我正在寻找一种触发JSF动作方法和AJAX侦听器的解决方案!

    我也对通用方法感兴趣,例如。 p:selectOneButton 生产

    <div id="mainForm:mainSelectOneButtonPrime" class="ui-selectonebutton ui-buttonset ui-widget ui-corner-all">
        <div class="ui-button ui-widget ui-state-default ui-button-text-only ui-corner-left">
            <input id="mainForm:mainSelectOneButtonPrime:0" name="mainForm:mainSelectOneButtonPrime" value="aPrime" class="ui-helper-hidden" type="radio">
            <span class="ui-button-text ui-c">aPrime</span>
        </div>
        <div class="ui-button ui-widget ui-state-default ui-button-text-only">
            <input id="mainForm:mainSelectOneButtonPrime:1" name="mainForm:mainSelectOneButtonPrime" value="bPrime" class="ui-helper-hidden" type="radio">
            <span class="ui-button-text ui-c">bPrime</span>
        </div>
        <div class="ui-button ui-widget ui-state-default ui-button-text-only ui-corner-right">
            <input id="mainForm:mainSelectOneButtonPrime:2" name="mainForm:mainSelectOneButtonPrime" value="cPrime" class="ui-helper-hidden" type="radio">
            <span class="ui-button-text ui-c">cPrime</span>
        </div>
    </div>
    <input name="javax.faces.ViewState" id="j_id1:javax.faces.ViewState:0" value="-5130093024933213812:2291815208147638618" autocomplete="off" type="hidden">
    

    这似乎与为生成的HTML没有任何共同之处 p: 选择器Radio

    我使用的是PrimeFaces 6.1。

    2 回复  |  直到 3 年前
        1
  •  4
  •   Kalle Richter    7 年前

    ui-helper-hidden-accessible 是一个 JQuery 布局辅助对象以直观地隐藏项目。您看到的单选按钮实际上是父元素, <div class="ui-radiobutton ui-widget"> .

    单击单选按钮标签可以解决该问题。“for”属性 put the focus 在输入标签上 associated with it

    @FindBy(css = "[for='mainForm:mainSelectOneRadioPrime:0']")
    private WebElement mainSelectOneRadioPrimeOption0;
    
        2
  •  3
  •   Florent B.    7 年前

    @盖伊有正确的答案。

    这里的问题是PrimeFaces在HTML上应用了自己的样式,HTML覆盖了您试图单击的元素。

    硒检查目标元素 mainForm:mainSelectOneRadio:0 ElementNotInteractableException (参见 event bubbling and propagation ).

    你可以通过访问 oneRadio.xhtml 通过右键点击检查单选按钮。您将看到所选的DOM元素和 <input>

    要解决此问题,请单击标签,因为它没有覆盖(请参阅@Guy的解决方案)。标签上有 for 属性,这意味着所有事件都转发到分配给的元素 对于 <输入(>); .

    您也可以直接单击覆盖。不过,您必须使用XPath来表示关系。

    目标公司的母公司 <输入(>); :

        @FindBy(xpath = "id('mainForm:mainSelectOneRadioPrime:2')/../..")  
        private WebElement mainSelectOneRadioPrimeOption0;
    

    或者首先 <td> 具有目标 <输入(>); :

        @FindBy(xpath = "//td[.//input[@id='mainForm:mainSelectOneRadioPrime:2']]")
        private WebElement mainSelectOneRadioPrimeOption0;
    
    推荐文章