This is an automated email from the ASF dual-hosted git repository.

benw pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git


The following commit(s) were added to refs/heads/master by this push:
     new 6ff6ded40 TAP5-2816: SeleniumTestCase replace By.link with By.xpath 
locator
6ff6ded40 is described below

commit 6ff6ded4047f55d7a5fd3b6027a500e04015a140
Author: Ben Weidig <[email protected]>
AuthorDate: Sat Jan 31 12:05:44 2026 +0100

    TAP5-2816: SeleniumTestCase replace By.link with By.xpath locator
---
 .../integration/appfolder/AppFolderTests.groovy    |  6 +++-
 .../apache/tapestry5/test/SeleniumTestCase.java    | 37 +++++++++++++++++++---
 tapestry-upload/src/test/webapp/Ajaxified.tml      |  2 +-
 3 files changed, 38 insertions(+), 7 deletions(-)

diff --git 
a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/appfolder/AppFolderTests.groovy
 
b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/appfolder/AppFolderTests.groovy
index 9a1563f64..894dcbe3b 100644
--- 
a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/appfolder/AppFolderTests.groovy
+++ 
b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/appfolder/AppFolderTests.groovy
@@ -31,7 +31,11 @@ class AppFolderTests extends GroovyTapestryCoreTestCase
     @Test
     void component_event_request()
     {
-        openLinks "t5app/", "show index page alert"
+        // Don't use "show index page alert" as second argument here, as the 
first one needs to be the acutal page
+        // not the folder to make it work.
+        openLinks "t5app/"
+
+        clickAndWait "link=show index page alert"
 
         assertTextPresent "index page alert"
     }
diff --git 
a/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java 
b/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java
index 55ca74927..e64bf20da 100644
--- 
a/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java
+++ 
b/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java
@@ -221,21 +221,21 @@ public abstract class SeleniumTestCase extends Assert 
implements Selenium
 
         final Runnable stopWebServer = launchWebServer(container, 
webAppFolder, contextPath, port, sslPort);
 
-//        FirefoxDriverManager.getInstance().setup();
         FirefoxDriverManager.firefoxdriver().setup();
 
         File ffProfileTemplate = new 
File(TapestryRunnerConstants.MODULE_BASE_DIR, 
"src/test/conf/ff_profile_template");
         DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
 
         FirefoxOptions options = new FirefoxOptions(desiredCapabilities); 
-//        options.setLogLevel(FirefoxDriverLogLevel.TRACE);
+        // options.setHeadless(true);
+        // options.setLogLevel(FirefoxDriverLogLevel.TRACE);
         
         if (ffProfileTemplate.isDirectory() && ffProfileTemplate.exists())
         {
             LOGGER.info("Loading Firefox profile from: {}", ffProfileTemplate);
             FirefoxProfile profile = new FirefoxProfile(ffProfileTemplate);
             options.setProfile(profile);
-//            profile.layoutOnDisk();
+            // profile.layoutOnDisk();
         }
         else 
         {
@@ -1727,7 +1727,10 @@ public abstract class SeleniumTestCase extends Assert 
implements Selenium
             {
                 try 
                 {
-                    
waitForCondition(ExpectedConditions.presenceOfElementLocated(By.linkText(text)),
 3);
+                    // TAP5-2816: Firefox Security Manager might veto 
By.linkText atoms. (NS_ERROR_XPC_SECURITY_MANAGER_VETO)
+                    // Using an XPath selector does the exact same thing.
+                    String xpath = "//a[normalize-space(.)=" + 
escapeXPathContent(text) + "]";
+                    
waitForCondition(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)), 
3);
                 }
                 catch (Exception e)
                 {
@@ -1935,7 +1938,10 @@ public abstract class SeleniumTestCase extends Assert 
implements Selenium
     {
         if (locator.startsWith("link="))
         {
-            return By.linkText(locator.substring(5));
+            // TAP5-2816: Replacing By.linkText with By.xpath to bypass 
Firefox Security Manager veto.
+            // By.link uses a JS "atom" to do its job, where xpath uses native 
browser functionality.
+            String text = locator.substring(5);
+            return By.xpath("//a[normalize-space(.)=" + 
escapeXPathContent(text) + "]");
         }
         else if (locator.startsWith("css="))
         {
@@ -1958,4 +1964,25 @@ public abstract class SeleniumTestCase extends Assert 
implements Selenium
             return By.id(locator);
         }
     }
+
+    /**
+     * TAP5-2816: Escapes a string for use in an XPath expression, as 
backslash escaping isn't supported
+     * - If no single quotes: wrap in single quotes: 'foo'
+     * - If single quotes present: wrap in double quotes: "foo'bar"
+     * - If both present: use concat(): concat('foo', "'", 'bar')
+     */
+    private static String escapeXPathContent(String text) {
+        if (!text.contains("'"))
+        {
+            return "'" + text + "'";
+        }
+
+        if (!text.contains("\""))
+        {
+            return "\"" + text + "\"";
+        }
+
+        // If both quote types are present, we must use: concat('foo', "'", 
'bar')
+        return "concat('" + text.replace("'", "', \"'\", '") + "')";
+    }
 }
\ No newline at end of file
diff --git a/tapestry-upload/src/test/webapp/Ajaxified.tml 
b/tapestry-upload/src/test/webapp/Ajaxified.tml
index 5f86c8f6a..6bdfde868 100644
--- a/tapestry-upload/src/test/webapp/Ajaxified.tml
+++ b/tapestry-upload/src/test/webapp/Ajaxified.tml
@@ -15,7 +15,7 @@
         <t:form>
             <t:errors/>
             <div t:type="any" t:id="injector">
-                <a href="#" id="trigger">add row</a>
+                <a href="#" id="trigger">Add row</a>
             </div>
 
             <br/>

Reply via email to