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/>