The Citrus community is happy to announce the release of Citrus 5.1.0! This release brings three new modules, major improvements to browser-based testing with Selenium and a fresh set of validation capabilities with AssertJ.
The release is packed with 21 new features and enhancements, 13 bug fixes and many dependency version updates. Here is a look at the highlights.
GraphQL support
Citrus 5.1.0 introduces a brand-new citrus-graphql module (#1797, docs) that adds first-class support for testing GraphQL APIs. You can send queries, mutations and subscriptions through a typed graphql() test action API, validate responses against SDL schemas, and simulate a GraphQL server for contract testing. The module builds on Spring GraphQL and supports Java, XML and YAML DSL out of the box.
given(graphql().client(graphqlClient)
.send()
.query("{ user(id: 1) { name email } }"));
then(graphql().client(graphqlClient)
.receive()
.validate("$.data.user.name", "John"));
AssertJ validation
The new citrus-validation-assertj module (#1782, docs) lets you use AssertJ assertion chains directly in your Citrus validation. You can write @assertj()@ expressions in expected message payloads or use the Java DSL with satisfies() factories. The module covers value assertions, header validation, container conditions and coexists seamlessly with existing Hamcrest matchers.
In the Java DSL, use satisfies() with AssertJ’s fluent API to validate JsonPath and XPath values or message headers:
$(receive(endpoint)
.message()
.type(MessageType.JSON)
.header("count", satisfies(Integer.class,
c -> assertThat(c).isBetween(40, 50)))
.validate(validation().jsonPath()
.expression("$.qty", satisfies(Integer.class,
q -> assertThat(q).isGreaterThan(5)))
.expression("$.status", satisfies(
s -> assertThat(s).asString().startsWith("OK")))));
In XML or YAML DSL, the @assertj()@ validation matcher lets you chain assertions directly in the expected value:
<receive endpoint="myEndpoint">
<message type="json">
<validate>
<json-path expression="$.qty"
value="@assertj(asInt().isBetween(1, 10))@"/>
<json-path expression="$.tags"
value="@assertj(asList().containsExactly('a', 'b'))@"/>
</validate>
</message>
<header>
<element name="Operation"
value="@assertj(isIn('sayHello', 'sayHi'))@"/>
</header>
</receive>
Playwright browser automation
Citrus 5.1.0 introduces citrus-playwright (#1714, docs), a new module for browser automation built on Playwright. Playwright offers fast, reliable cross-browser testing with auto-waiting, network interception and multi-context isolation — and Citrus now wraps it in a familiar endpoint and action API that integrates naturally with your integration test scenarios.
The module ships with Playwright 1.63.0 and a rich set of capabilities out of the box:
-
Typed
playwright()test actions for navigation, clicks, form fills, screenshots, tracing, aria snapshots, WebAuthn passkeys, screencast recording and more (#1737) - XML and YAML DSL elements for all Playwright actions (#1745)
- Browser-session HTTP client that sends API requests carrying the browser’s cookies and auth state, bridging UI and API testing in a single scenario (#1751)
- Cucumber steps via a companion citrus-cucumber-playwright module for BDD-style browser tests (#1803)
- Endpoint catalog integration so AI-assisted coding and IDE completion discover the Playwright endpoint (#1775)
Selenium improvements
Selenium-based browser testing (docs) has been modernized with a wave of new actions and quality-of-life fixes:
- Interaction actions — double click, right click, drag and drop, press keys and extended dropdown select (#1819)
- Verify and extract actions with variable-aware XML/YAML locators to check page URL, title, element state and store values as test variables (#1821)
- Frame navigation, cookie management and JavaScript result variable support (#1830)
- Browser options — headless mode, arguments, window size and timeouts configurable on the endpoint (#1833)
- Several bug fixes covering start-page resolution, element lookup error handling, JS error collection and cache clearing (#1812)
Test behavior and validation improvements
- Named and composable test behaviors — behaviors can now carry a name, be nested and scoped, so they compose cleanly and appear with meaningful labels in reports (#1752)
- Typed test results — ask a question in a test behavior and receive a typed answer back for downstream assertions (#1757)
-
Combinator validation matchers —
@allOf()@,@anyOf()@and@not()@let you compose multiple validation matchers into a single expression (#1768, docs) -
Comparison validation matchers —
@greaterThanOrEqualTo()@and@lowerThanOrEqualTo()@complement the existing comparison set (#1767, docs) -
Plain-Java SQL result set validation — validate SQL query results with a typed
SqlResultSetValidatorcallback and POJO row mapping instead of scripts (#619, docs)
Notable fixes
-
TestContext isolation — each dynamic test in
JUnitCitrusTestnow receives its own context, preventing final-action side effects across tests (#1816) -
Content-Type on bodyless requests — HTTP client no longer sends
Content-Type: text/plainon GET and other bodyless requests (#1826) - CitrusSettings refactoring — static final fields replaced with dynamic accessor methods so settings changes take effect at runtime (#1771)
-
Send action error handling — send actions inside
assertExceptionno longer hang when message creation fails (#1798)
For the full list of changes see the release changelog.
Major library versions
Citrus 5.1.0 ships with the following major dependency versions:
| Library | Version |
|---|---|
| Apache Camel | 4.23.0 |
| Quarkus | 3.40.1 |
| Spring Framework | 7.0.9 |
| Spring Boot | 4.1.1 |
| Kafka | 4.4.0 |
| Selenium | 4.51.0 |
| Playwright | 1.63.0 |
| Cucumber | 8.0.4 |
| JUnit Jupiter | 6.1.3 |
| TestNG | 7.12.0 |
| Testcontainers | 2.0.5 |
| Kubernetes Client | 7.9.0 |
| Apache ActiveMQ Artemis | 2.57.0 |
| Vert.x | 4.5.35 |
| Jetty | 12.1.14 |
| Netty | 4.2.19.Final |
Java 17 — last supported release
Citrus 5.1.0 is the last release to support Java 17. Starting with Citrus 5.2.x, the minimum required Java version will be Java 21. If you are still on Java 17, please plan your migration accordingly before upgrading to the next release line.
Update
Update the Citrus BOM in your pom.xml:
<dependency>
<groupId>org.citrusframework</groupId>
<artifactId>citrus-bom</artifactId>
<version>5.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Thank you to everyone who contributed to this release!