{{ message }}
Repository navigation
Conversation
play-test, which Play's sbt plugin adds to every project, and play-specs2 brought Selenide, Selenium with all of its browser drivers and HtmlUnit to the tests of every application, about 50 artifacts, although most tests don't use a browser. Excluding them broke tests without a browser too: play.api.test.Helpers and play.test.Helpers failed with a NoClassDefFoundError for HtmlUnitDriver, and Scala could not compile any PlaySpecification (on Scala 3 not even code using Helpers) without Selenium's WebDriver. - play-test and play-specs2 now declare selenide-core and htmlunit3-driver as optional dependencies. play-test only depends on the small selenium-api, which contains WebDriver. - The new play-test-browser artifact (sbt: playTestBrowser) contains no code and brings these dependencies in matching versions. - In Scala, the browser constants are lazy and typed Class[? <: WebDriver], and so is the driver class that the specs2 WithBrowser constructor takes. In Java, they are looked up by name and are null without the dependencies; Helpers then explains how to add them. - The new Play-Test-Without-Browser project tests Helpers, PlaySpecification, WithApplication and WithServer without the optional dependencies. The new scripted test test-browser-dependencies checks the published artifacts: an application gets the browser dependencies only with playTestBrowser. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move form submission into the existing Java browser base class so Scala can load TestBrowser signatures without completing Selenide collection types. Keep the Seq signature for compiled Scala callers and preserve named arguments with Java parameter metadata. Exercise named, spliced and empty form submissions, and extend the published-artifact consumer fixture. Verify the four failing Scala 3.next module compilations and the browser and no-browser suites on Scala 2.13, 3.3 and 3.next.
While TestBrowser.submit was defined in Scala, Scala 3.10 failed to
compile `"a" -> "b"` in a PlaySpecification without Selenide ("Bad
symbolic reference" to ElementsCollection), also against artifacts
built with Scala 3.3. The without-browser project and the scripted
consumer test now check it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
Author
The scripted test resolves Play from the local Ivy repository, so it doesn't check the Maven POMs that Gradle and Maven users get. The Gradle plugin's functional tests now build the same two applications from Play's POMs: without play-test-browser, Selenide, HtmlUnit and the browser drivers must be missing. Gradle runs the specs through JUnit, so they get JUnitRunner. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
play-testandplay-specs2brought Selenide, Selenium with all of its browser drivers and HtmlUnit to the tests of every application. Play's sbt plugin addsplay-testto every project, so every application got them, although most tests don't use a browser.play-testresolves to 111 artifacts; 52 of them only come from the test browser.Excluding them, as #13589 describes, broke tests without a browser too:
play.api.test.Helpersandplay.test.Helpersfail on first use withNoClassDefFoundError: org/openqa/selenium/htmlunit/HtmlUnitDriver, because the browser constants (HTMLUNIT,FIREFOX, …) are initialized eagerly.PlaySpecificationwithout Selenium (on Scala 2.13 and 3), because it mixes inPlayRunners, whose browser runners mentionWebDriver. On Scala 3, even code that only callsHelpersdoesn't compile.Changes:
play-testandplay-specs2declareselenide-coreandhtmlunit3-driveras optional dependencies, so applications no longer get them.selenium-apistays:play-teststill depends on Selenium'sselenium-api(240 KB, plus the 3 KBjspecify), which containsWebDriver. Without it, Scala could not compilePlaySpecification, as described above. Its version must match the Selenium version Selenide brings, so Scala Steward doesn't update it on its own.play-test-browserartifact: it contains no code and bringsplay-testand the test browser's dependencies, in matching versions. The sbt plugin offers it asplayTestBrowser, but doesn't add it automatically.submitis inherited from the existing Java browser base class. This keeps Selenide collection types out ofTestBrowser's Scala signature, which otherwise broke compilation of non-browser tests. Positional, named, spliced and empty-field calls still work; the Scala sequence overload preserves the signature used by compiled callers. A method reference needs an expected function type to select that overload, as shown in the migration guide.HTMLUNIT,FIREFOX,CHROME,EDGEandSAFARIare lazy and typedClass[? <: WebDriver]. The constructor of the specs2WithBrowserthat takes a driver class now takesClass[? <: WebDriver]as well, so thatnew WithBrowser(FIREFOX, app, port)keeps compiling.nullwithout the dependencies.Helpers.testBrowser(...)andHelpers.running(server, browserClass, ...)then fail with an error that explains how to addplay-test-browser, before touching any browser class.For applications:
selenium-api), andHelpers,PlaySpecification,WithApplicationandWithServerwork without them.libraryDependencies += playTestBrowser % Test, ororg.playframework:play-test-browser_2.13/_3with Gradle or Maven. Normal browser calls still work. In Scala, the browser constants are now typedClass[? <: WebDriver], so code that needs the exact driver class type, likeval c: Class[FirefoxDriver] = FIREFOX, usesclassOf[FirefoxDriver]instead. Method references tosubmitneed an expected function type to select its Scala sequence overload; the migration guide includes an example. Without the dependency, they fail to compile or to run, because Selenide, the browser drivers or HtmlUnit are missing.Later: the browser classes and helpers could move into
play-test-browseritself, so thatplay-testcontains no Selenium code at all. This PR keeps them inplay-test, so that browser tests keep their imports and APIs in the same release that switches them to Selenide (#14337).Testing
eb938021b0): the Check workflow passed: all eight main-test lanes, eight documentation-test lanes, 48 scripted-test jobs, four Gradle-plugin jobs, formatting and binary compatibility checks. The matrix covers Java 17/25 and Scala 2.13, 3.3, 3.9 and3.next; scripted tests cover sbt 1 and sbt 2. This run passed on its first attempt."email" -> "user@example.com"in aPlaySpecificationwithout the browser dependencies. The new example fails to compile on the original commit (7579549e58) with Scala 3.10.0-RC3 and the missingElementsCollection/Terror. With the fix, the without-browser suite passes on Scala 3.10.0-RC3, 3.3.8 and 2.13.18; rootvalidateCodepasses too.Play-Ehcache,Play-JDBC,Play-AHC-WSandPlay-Filters-Helperson Scala3.next(3.10.0-RC3). All four compile locally after movingsubmitto the Java base class. Browser form submissions and tests without browser dependencies pass on Scala 2.13.18, 3.3.8 and 3.10.0-RC3. The explicit method-reference replacement passes on 2.13.18 and 3.3.8. MiMa on both published Scala lines, root and documentationvalidateCode, API docs, and documentation link/snippet validation pass. A later CI run exposed an ambiguousActionoverload in the new scripted fixture on Scala 3. Explicit request and result types fix that. The scripted consumer submits a form with named and spliced arguments against published jars, and now passes locally on Scala 2.13.18 and 3.3.8 with both sbt 1.12.15 and sbt 2.Play-Test-Without-Browserproject excludesselenide-coreandhtmlunit3-driver, like an application withoutplay-test-browser. On Scala 2.13 and 3.3.8:PlaySpecification,Helpers,WithApplicationandWithServerwork, and the browsers and Selenide are not on the classpath.Helpers,running(app, ...)andrunning(testServer, ...)work, andHelpers.testBrowser()fails with the error that namesplayTestBrowser.test-browser-dependenciesbuilds two applications against the locally published Play (sbt's Ivy publication), as CI's scripted tests do, without excluding anything:playTestBrowser: its specs2 and JUnit tests check that Selenide, HtmlUnit and the browser drivers are missing, so the test fails ifplay-testorplay-specs2bring them again. They also check thatPlaySpecification,WithApplication,WithServerand JavaHelperswork, thatHelpers.HTMLUNITisnull, and thattestBrowser()explains the missing dependency.playTestBrowser: specs2WithBrowser(with theHTMLUNITconstant) and Javarunning(testServer, HTMLUNIT, ...)open a page of the application with HtmlUnit.WithBrowserwith a driver class: the newWithBrowserSpecinPlay-Integration-TestpassesHTMLUNITtoWithBrowser, without and with an explicit driver type. Both failed to compile with the previous constructor, and pass on Scala 2.13 and 3.3.8.Play-Integration-Testnow depends onPlay-Test-Browserfor itsWithBrowserexamples (also those of Reset the port of specs2WithServerandWithBrowseralso when an example fails #14338), like an application withplayTestBrowser; they pass on Scala 2.13 and 3.3.8. ThePlay-TestandPlay-Specs2tests, MiMa,validateCode, and the documentation's browser examples (Java and Scala, now withPlay-Test-Browser) and validation pass.HelpersTestchecks that the Java constants, now looked up by name, are the driver classes, and that anulldriver class gets the explaining error.selenide-coreoptional flag from the localplay-testPOM and failed as expected; the POM was restored. Both specs use JUnitRunner for Gradle; the earlier sbt consumer checks still passed with each spec running once.play-testandplay-specs2markselenide-coreandhtmlunit3-driverasoptional, andplay-test-browserdepends on them normally.play-test-browser: of the Selenium family, onlyselenium-apiis on the test classpath. APlaySpecificationusingHelpers,WithApplicationandWithServer, and a Java test usingHelpersandtestBrowser()'s error, pass.play-test-browser:WithBrowserandrunningWithPort(..., HTMLUNIT)in specs2, andrunning(testServer(), HTMLUNIT, ...)in Java, pass with HtmlUnit.play-testnow resolves to 60 artifacts instead of 111 (51 fewer); withplay-test-browser, it's 112.AI assistance
Claude (Anthropic) was used to analyse the issue, implement this change, write the tests and draft this pull request. OpenAI Codex reviewed the approach and implemented the Scala signature fix and its compatibility notes after CI exposed the issue. I reviewed the result before submitting.