This is an automated email from the ASF dual-hosted git repository. benw pushed a commit to branch javax in repository https://gitbox.apache.org/repos/asf/tapestry-5.git
commit dcffa6d2c675056ba1e1f2774d2e706732564f6b 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 56dd77954..bb477cecf 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 @@ -218,21 +218,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 { @@ -1724,7 +1724,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) { @@ -1932,7 +1935,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=")) { @@ -1955,4 +1961,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/>
