Repository: assertj/assertj
Pull request #3757 (2025-01-27 21:23:53)

chore(deps): bump kotlin.version from 2.1.0 to 2.1.10
Bumps `kotlin.version` from 2.1.0 to 2.1.10.
Updates `org.jetbrains.kotlin:kotlin-stdlib` from 2.1.0 to 2.1.10
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/JetBrains/kotlin/releases">org.jetbrains.kotlin:kotlin-stdlib's releases</a>.</em></p>
<blockquote>
<h2>Kotlin 2.1.10</h2>
<h2>Changelog</h2>
<h3>Compiler</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73858"><code>KT-73858</code></a> Compose  / iOS: NullPointerException on building</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73454"><code>KT-73454</code></a> K2: Fix type parameters mapping for typealiases with inner RHS</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73043"><code>KT-73043</code></a> K2 Compiler does not allow references to inner constructors with typealiases</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-74040"><code>KT-74040</code></a> Compilation of inner class usage does not check the visibility of parent class during compilation in different rounds</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73339"><code>KT-73339</code></a> K2: &quot;VerifyError: Bad type on operand stack&quot; because of missing implicit cast on generic field receiver with star projection</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-72585"><code>KT-72585</code></a> K2: Compilation failure when upgrading to Kotlin 2.0.20+: Cannot replace top-level type with star projection: S</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73399"><code>KT-73399</code></a> compile-time JVM codegen failure on a KProperty argument of a KSuspendFunction parameter</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-72725"><code>KT-72725</code></a> KMP: Unsupported actualization of inherited java field in expect class</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73153"><code>KT-73153</code></a> K2: Standalone diagnostics on type arguments are not reported</li>
</ul>
<h3>Compose compiler</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/CMP-5680"><code>CMP-5680</code></a> Compose compiler: unexpected stability warnings for classes compiled with 2.0.10</li>
<li><a href="https://issuetracker.google.com/issues/381407900"><code>b/381407900</code></a> Avoid adding Compose annotations on synthetic classes</li>
</ul>
<h3>IR. Inlining</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73981"><code>KT-73981</code></a> Cherry-pick the fix for KT-73482 to 2.1.10</li>
</ul>
<h3>JavaScript</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/KT-70778"><code>KT-70778</code></a> Kotlin Js companion is undefined  in production build</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73130"><code>KT-73130</code></a> KJS: Missed <code>break</code> for do/while in generated JS code</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-58797"><code>KT-58797</code></a> Optimize the code generated for objects on JS and Wasm backends</li>
</ul>
<h3>Klibs</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/KT-70146"><code>KT-70146</code></a> [KLIB Resolve] Don't fail on nonexistent transitive dependency</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73951"><code>KT-73951</code></a> Workaround for &quot;Partial linkage engine may not patch some discrepancies in IR when compiling Kotlin/Native static caches&quot; in 2.1.10</li>
</ul>
<h3>Native</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73559"><code>KT-73559</code></a> K/Native: AndroidNativeArm64 linking fails starting from Kotlin 2.1.0</li>
</ul>
<h3>Tools. CLI</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73967"><code>KT-73967</code></a> JDK 25: &quot;IllegalArgumentException: 25-ea&quot; with EA builds</li>
</ul>
<h3>Tools. Daemon</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73311"><code>KT-73311</code></a> &quot;Unable to release compile session, maybe daemon is already down&quot; flakiness</li>
</ul>
<h3>Tools. Gradle</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73728"><code>KT-73728</code></a> 'generatePomFileForMavenPublication' creates pom with dependencies with 'unspecified' version</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md">org.jetbrains.kotlin:kotlin-stdlib's changelog</a>.</em></p>
<blockquote>
<h2>2.1.10</h2>
<h3>Compiler</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73858"><code>KT-73858</code></a> Compose  / iOS: NullPointerException on building</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73454"><code>KT-73454</code></a> K2: Fix type parameters mapping for typealiases with inner RHS</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73043"><code>KT-73043</code></a> K2 Compiler does not allow references to inner constructors with typealiases</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-74040"><code>KT-74040</code></a> Compilation of inner class usage does not check the visibility of parent class during compilation in different rounds</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73339"><code>KT-73339</code></a> K2: &quot;VerifyError: Bad type on operand stack&quot; because of missing implicit cast on generic field receiver with star projection</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-72585"><code>KT-72585</code></a> K2: Compilation failure when upgrading to Kotlin 2.0.20+: Cannot replace top-level type with star projection: S</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73399"><code>KT-73399</code></a> compile-time JVM codegen failure on a KProperty argument of a KSuspendFunction parameter</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-72725"><code>KT-72725</code></a> KMP: Unsupported actualization of inherited java field in expect class</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73153"><code>KT-73153</code></a> K2: Standalone diagnostics on type arguments are not reported</li>
</ul>
<h3>Compose compiler</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/CMP-5680"><code>CMP-5680</code></a> Compose compiler: unexpected stability warnings for classes compiled with 2.0.10</li>
<li><a href="https://issuetracker.google.com/issues/381407900"><code>b/381407900</code></a> Avoid adding Compose annotations on synthetic classes</li>
</ul>
<h3>IR. Inlining</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73981"><code>KT-73981</code></a> Cherry-pick the fix for KT-73482 to 2.1.10</li>
</ul>
<h3>JavaScript</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/KT-70778"><code>KT-70778</code></a> Kotlin Js companion is undefined  in production build</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73130"><code>KT-73130</code></a> KJS: Missed <code>break</code> for do/while in generated JS code</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-58797"><code>KT-58797</code></a> Optimize the code generated for objects on JS and Wasm backends</li>
</ul>
<h3>Klibs</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/KT-70146"><code>KT-70146</code></a> [KLIB Resolve] Don't fail on nonexistent transitive dependency</li>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73951"><code>KT-73951</code></a> Workaround for &quot;Partial linkage engine may not patch some discrepancies in IR when compiling Kotlin/Native static caches&quot; in 2.1.10</li>
</ul>
<h3>Native</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73559"><code>KT-73559</code></a> K/Native: AndroidNativeArm64 linking fails starting from Kotlin 2.1.0</li>
</ul>
<h3>Tools. CLI</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73967"><code>KT-73967</code></a> JDK 25: &quot;IllegalArgumentException: 25-ea&quot; with EA builds</li>
</ul>
<h3>Tools. Daemon</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73311"><code>KT-73311</code></a> &quot;Unable to release compile session, maybe daemon is already down&quot; flakiness</li>
</ul>
<h3>Tools. Gradle</h3>
<ul>
<li><a href="https://youtrack.jetbrains.com/issue/KT-73728"><code>KT-73728</code></a> 'generatePomFileForMavenPublication' creates pom with dependencies with 'unspecified' version</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/JetBrains/kotlin/commit/6dff5659f42b0b90863d10ee503efd5a8ebb1034"><code>6dff565</code></a> Add ChangeLog for 2.1.10-RC2</li>
<li><a href="https://github.com/JetBrains/kotlin/commit/5e6f6a655b9efe4aa35387b60143a6c4611e8c2c"><code>5e6f6a6</code></a> [tests] Turned on passing tests</li>
<li><a href="https://github.com/JetBrains/kotlin/commit/b968b02674e99f3fb423843b27d382f110b25468"><code>b968b02</code></a> [K/N] Skip missing dependencies during cache building</li>
<li><a href="https://github.com/JetBrains/kotlin/commit/8b57d4490f9708a6458c5822a72567778ab1d59c"><code>8b57d44</code></a> [CMP] no metadata annotations on synthetic classes</li>
<li><a href="https://github.com/JetBrains/kotlin/commit/f82abd90b3b1de74a89a10034c2ea843308c8fa2"><code>f82abd9</code></a> [AA] Lazily compute the effective visibility in FIR stub-based deserializer</li>
<li><a href="https://github.com/JetBrains/kotlin/commit/618eaff0cdd5dfe40cb37c8fd2c679951d0ff51e"><code>618eaff</code></a> [FIR] Don't render lazy attributes with <code>null</code> value in FIR renderer</li>
<li><a href="https://github.com/JetBrains/kotlin/commit/5f5af3826c2aca1c43e1644830085db3e1cc6a7d"><code>5f5af38</code></a> [FIR] Remove incorrect fast-path from <a href="https://github.com/PublishedAPI"><code>@​PublishedAPI</code></a> computation for binary de...</li>
<li><a href="https://github.com/JetBrains/kotlin/commit/435080bbd908b4604c4d6e74696506adeba5f453"><code>435080b</code></a> [FIR] Consider effective visibility of parent class during deserialization</li>
<li><a href="https://github.com/JetBrains/kotlin/commit/05e92d4ee57784037b6eb759705b2ab58653cc7f"><code>05e92d4</code></a> [Test] Reproduce KT-74040 in AA tests</li>
<li><a href="https://github.com/JetBrains/kotlin/commit/c49acfbcb1262d58ef541340e8f29043665d2e62"><code>c49acfb</code></a> [Test] Render <code>isPublicApi</code> attribute in AA tests</li>
<li>Additional commits viewable in <a href="https://github.com/JetBrains/kotlin/compare/v2.1.0...v2.1.10">compare view</a></li>
</ul>
</details>
<br />

Updates `org.jetbrains.kotlin:kotlin-maven-plugin` from 2.1.0 to 2.1.10


Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index a3facc5d7..71661eb81 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -56,7 +56,7 @@ jobs:
       matrix:
         # https://kotlinlang.org/docs/releases.html#release-details
         # https://kotlinlang.org/docs/eap.html#build-details
-        kotlin: [1.9.25, 2.0.21, 2.1.10-RC2, 2.1.20-Beta1]
+        kotlin: [1.9.25, 2.0.21, 2.1.20-Beta2]
     runs-on: ubuntu-latest
 
     steps:
diff --git a/assertj-core/pom.xml b/assertj-core/pom.xml
index 724bac7b4..cc320db13 100644
--- a/assertj-core/pom.xml
+++ b/assertj-core/pom.xml
@@ -28,7 +28,7 @@
     <spotless.skip>false</spotless.skip>
     <jacoco.skip>true</jacoco.skip> <!-- https://github.com/assertj/assertj/issues/3580 -->
     <!-- Dependency versions -->
-    <byte-buddy.version>1.16.1</byte-buddy.version>
+    <byte-buddy.version>1.17.0</byte-buddy.version>
     <hamcrest.version>3.0</hamcrest.version>
     <!-- Plugin versions -->
     <cdg.pitest.version>1.1.4</cdg.pitest.version>
@@ -130,7 +130,7 @@
     <dependency>
       <groupId>nl.jqno.equalsverifier</groupId>
       <artifactId>equalsverifier</artifactId>
-      <version>3.18.1</version>
+      <version>3.18.2</version>
       <scope>test</scope>
     </dependency>
     <dependency>
@@ -319,15 +319,15 @@
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <executions>
+          <!-- FIXME https://github.com/assertj/assertj/issues/3446 -->
           <execution>
-            <id>jdk9</id>
+            <id>module</id>
             <goals>
               <goal>compile</goal>
             </goals>
             <configuration>
-              <release>9</release>
               <compileSourceRoots>
-                <compileSourceRoot>${project.basedir}/src/main/java9</compileSourceRoot>
+                <compileSourceRoot>${project.basedir}/src/main/module</compileSourceRoot>
               </compileSourceRoots>
               <multiReleaseOutput>true</multiReleaseOutput>
             </configuration>
@@ -420,6 +420,10 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-javadoc-plugin</artifactId>
+        <configuration>
+          <!-- FIXME https://github.com/assertj/assertj/issues/3446 -->
+          <legacyMode>true</legacyMode>
+        </configuration>
       </plugin>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
diff --git a/assertj-core/src/main/java/org/assertj/core/api/AbstractByteArrayAssert.java b/assertj-core/src/main/java/org/assertj/core/api/AbstractByteArrayAssert.java
index a8e0159bf..2ec0c3ea7 100644
--- a/assertj-core/src/main/java/org/assertj/core/api/AbstractByteArrayAssert.java
+++ b/assertj-core/src/main/java/org/assertj/core/api/AbstractByteArrayAssert.java
@@ -1343,6 +1343,26 @@ public abstract class AbstractByteArrayAssert<SELF extends AbstractByteArrayAsse
     return new StringAssert(Base64.getEncoder().encodeToString(actual)).withAssertionState(myself);
   }
 
+  /**
+   * @deprecated use {@link #asBase64Encoded()} instead.
+   * <p>
+   * Encodes the actual array into a Base64 string, the encoded string becoming the new object under test.
+   * <p>
+   * Examples:
+   * <pre><code class='java'> // assertion succeeds
+   * assertThat("AssertJ".getBytes()).encodedAsBase64().isEqualTo(&quot;QXNzZXJ0Sg==&quot;);</code></pre>
+   *
+   * @return a new {@link StringAssert} instance whose string under test is the result of the encoding.
+   * @throws AssertionError if the actual value is {@code null}.
+   *
+   * @since 3.16.0
+   */
+  @Deprecated
+  @CheckReturnValue
+  public AbstractStringAssert<?> encodedAsBase64() {
+    return asBase64Encoded();
+  }
+
   private static byte[] toPrimitiveByteArray(Byte[] values) {
     byte[] bytes = new byte[values.length];
     range(0, values.length).forEach(i -> bytes[i] = values[i]);
diff --git a/assertj-core/src/main/java/org/assertj/core/api/AbstractCharSequenceAssert.java b/assertj-core/src/main/java/org/assertj/core/api/AbstractCharSequenceAssert.java
index c1cc3ce1e..1beb4d750 100644
--- a/assertj-core/src/main/java/org/assertj/core/api/AbstractCharSequenceAssert.java
+++ b/assertj-core/src/main/java/org/assertj/core/api/AbstractCharSequenceAssert.java
@@ -15,6 +15,7 @@ package org.assertj.core.api;
 import static java.lang.Character.isWhitespace;
 import static java.util.Arrays.stream;
 import static java.util.stream.Collectors.toCollection;
+import static org.assertj.core.api.Assertions.contentOf;
 import static org.assertj.core.error.ShouldBeASCII.shouldBeASCII;
 import static org.assertj.core.error.ShouldBeAlphabetic.shouldBeAlphabetic;
 import static org.assertj.core.error.ShouldBeAlphanumeric.shouldBeAlphanumeric;
@@ -34,6 +35,7 @@ import static org.assertj.core.internal.Strings.doCommonCheckForCharSequence;
 import static org.assertj.core.internal.Strings.removeAllWhitespaces;
 import static org.assertj.core.util.IterableUtil.toArray;
 
+import java.io.File;
 import java.io.LineNumberReader;
 import java.text.Normalizer;
 import java.util.Comparator;
@@ -333,6 +335,67 @@ public abstract class AbstractCharSequenceAssert<SELF extends AbstractCharSequen
     if (containsOnlyWhitespaces(actual)) throw assertionError(shouldNotContainOnlyWhitespaces(actual));
   }
 
+  /**
+   * Verifies that the actual {@code CharSequence} is blank, i.e. consists of one or more whitespace characters
+   * (according to {@link Character#isWhitespace(char)}).
+   * <p>
+   * These assertions will succeed:
+   * <pre><code class='java'> assertThat(" ").isJavaBlank();
+   * assertThat("     ").isJavaBlank();</code></pre>
+   *
+   * Whereas these assertions will fail:
+   * <pre><code class='java'> assertThat("a").isJavaBlank();
+   * assertThat(" b").isJavaBlank();
+   * assertThat("").isJavaBlank();
+   * String nullString = null;
+   * assertThat(nullString).isJavaBlank(); </code></pre>
+   *
+   * @return {@code this} assertion object.
+   * @throws AssertionError if the actual {@code CharSequence} is not blank.
+   * @since 2.6.0 / 3.6.0
+   * @deprecated Use {@link #isBlank()} instead.
+   */
+  @Deprecated
+  public SELF isJavaBlank() {
+    assertJavaBlank(actual);
+    return myself;
+  }
+
+  private void assertJavaBlank(CharSequence actual) {
+    if (!containsOnlyWhitespaces(actual)) throw assertionError(shouldBeBlank(actual));
+  }
+
+  /**
+   * Verifies that the actual {@code CharSequence} is not blank, i.e. either is {@code null}, empty or
+   * contains at least one non-whitespace character (according to {@link Character#isWhitespace(char)}).
+   * <p>
+   * These assertions will succeed:
+   * <pre><code class='java'> assertThat("a").isNotJavaBlank();
+   * assertThat(" b").isNotJavaBlank();
+   * assertThat(" c ").isNotJavaBlank();
+   * assertThat("").isNotJavaBlank();
+   * String nullString = null;
+   * assertThat(nullString).isNotJavaBlank();</code></pre>
+   *
+   * Whereas these assertions will fail:
+   * <pre><code class='java'> assertThat(" ").isNotJavaBlank();
+   * assertThat("   ").isNotJavaBlank();</code></pre>
+   *
+   * @return {@code this} assertion object.
+   * @throws AssertionError if the actual {@code CharSequence} is blank.
+   * @since 2.6.0 / 3.6.0
+   * @deprecated Use {@link #isNotBlank()} instead.
+   */
+  @Deprecated
+  public SELF isNotJavaBlank() {
+    assertNotJavaBlank(actual);
+    return myself;
+  }
+
+  private void assertNotJavaBlank(CharSequence actual) {
+    if (containsOnlyWhitespaces(actual)) throw assertionError(shouldNotBeBlank(actual));
+  }
+
   /**
    * Verifies that the actual {@code CharSequence} has the expected length using the {@code length()} method.
    * <p>
@@ -1337,6 +1400,89 @@ public abstract class AbstractCharSequenceAssert<SELF extends AbstractCharSequen
     return myself;
   }
 
+  /**
+   * @deprecated
+   *
+   * This assertion has some limitations, for example it does not handle tab vs space and would fail if elements are the same but
+   * in a different order.<br>
+   * The recommended approach is <a href="https://github.com/xmlunit/user-guide/wiki">XML Unit</a> which is able to deal with
+   * these limitations and provides many more features like XPath support and schema validation.
+   * <p>
+   * Original javadoc:
+   * <p>
+   * Verifies that the actual {@code CharSequence} is equal to the given XML {@code CharSequence} after both have been
+   * formatted the same way.
+   * <p>
+   * Example:
+   * <pre><code class='java'> String expectedXml =
+   *     &quot;&lt;rings&gt;\n&quot; +
+   *         &quot;  &lt;bearer&gt;\n&quot; +
+   *         &quot;    &lt;name&gt;Frodo&lt;/name&gt;\n&quot; +
+   *         &quot;    &lt;ring&gt;\n&quot; +
+   *         &quot;      &lt;name&gt;one ring&lt;/name&gt;\n&quot; +
+   *         &quot;      &lt;createdBy&gt;Sauron&lt;/createdBy&gt;\n&quot; +
+   *         &quot;    &lt;/ring&gt;\n&quot; +
+   *         &quot;  &lt;/bearer&gt;\n&quot; +
+   *         &quot;&lt;/rings&gt;&quot;;
+   *
+   * // No matter how your xml string is formatted, isXmlEqualTo is able to compare it's content with another xml String.
+   * String oneLineXml = &quot;&lt;rings&gt;&lt;bearer&gt;&lt;name&gt;Frodo&lt;/name&gt;&lt;ring&gt;&lt;name&gt;one ring&lt;/name&gt;&lt;createdBy&gt;Sauron&lt;/createdBy&gt;&lt;/ring&gt;&lt;/bearer&gt;&lt;/rings&gt;&quot;;
+   * assertThat(oneLineXml).isXmlEqualTo(expectedXml);
+   *
+   * String xmlWithNewLine =
+   *     &quot;&lt;rings&gt;\n&quot; +
+   *         &quot;&lt;bearer&gt;   \n&quot; +
+   *         &quot;  &lt;name&gt;Frodo&lt;/name&gt;\n&quot; +
+   *         &quot;  &lt;ring&gt;\n&quot; +
+   *         &quot;    &lt;name&gt;one ring&lt;/name&gt;\n&quot; +
+   *         &quot;    &lt;createdBy&gt;Sauron&lt;/createdBy&gt;\n&quot; +
+   *         &quot;  &lt;/ring&gt;\n&quot; +
+   *         &quot;&lt;/bearer&gt;\n&quot; +
+   *         &quot;&lt;/rings&gt;&quot;;
+   * assertThat(xmlWithNewLine).isXmlEqualTo(expectedXml);
+   *
+   * // You can compare it with oneLineXml
+   * assertThat(xmlWithNewLine).isXmlEqualTo(oneLineXml);
+   *
+   * // Tip : use isXmlEqualToContentOf assertion to compare your XML String with the content of an XML file :
+   * assertThat(oneLineXml).isXmlEqualToContentOf(new File(&quot;src/test/resources/formatted.xml&quot;));</code></pre>
+   *
+   * @param expectedXml the XML {@code CharSequence} to which the actual {@code CharSequence} is to be compared to.
+   * @return {@code this} assertion object to chain other assertions.
+   * @throws NullPointerException if the given {@code CharSequence} is {@code null}.
+   * @throws AssertionError if the actual {@code CharSequence} is {@code null} or is not the same XML as the given XML
+   *           {@code CharSequence}.
+   * @see <a href="https://github.com/xmlunit/user-guide/wiki">XML Unit</a>
+   * @see <a href="https://github.com/xmlunit/user-guide/wiki/Providing-Input-to-XMLUnit">XML Unit XML source input</a>
+   */
+  @Deprecated
+  public SELF isXmlEqualTo(CharSequence expectedXml) {
+    strings.assertXmlEqualsTo(info, actual, expectedXml);
+    return myself;
+  }
+
+  /**
+   * Verifies that the actual {@code CharSequence} is equal to the content of the given file.
+   * <p>
+   * This is a handy shortcut that calls : {@code isXmlEqualTo(contentOf(xmlFile))}
+   * </p>
+   * Example:
+   * <pre><code class='java'> // You can easily compare your XML String to the content of an XML file, whatever how formatted they are.
+   * String oneLineXml = &quot;&lt;rings&gt;&lt;bearer&gt;&lt;name&gt;Frodo&lt;/name&gt;&lt;ring&gt;&lt;name&gt;one ring&lt;/name&gt;&lt;createdBy&gt;Sauron&lt;/createdBy&gt;&lt;/ring&gt;&lt;/bearer&gt;&lt;/rings&gt;&quot;;
+   * assertThat(oneLineXml).isXmlEqualToContentOf(new File(&quot;src/test/resources/formatted.xml&quot;));</code></pre>
+   *
+   * @param xmlFile the file to read the expected XML String to compare with actual {@code CharSequence}
+   * @return {@code this} assertion object to chain other assertions.
+   * @throws NullPointerException if the given {@code File} is {@code null}.
+   * @throws AssertionError if the actual {@code CharSequence} is {@code null} or is not the same XML as the content of
+   *           given {@code File}.
+   */
+  @Deprecated
+  public SELF isXmlEqualToContentOf(File xmlFile) {
+    isXmlEqualTo(contentOf(xmlFile));
+    return myself;
+  }
+
   /**
    * Do not use this method.
    *
diff --git a/assertj-core/src/main/java/org/assertj/core/api/AbstractClassAssert.java b/assertj-core/src/main/java/org/assertj/core/api/AbstractClassAssert.java
index be4ef5e4b..50d00b2b2 100644
--- a/assertj-core/src/main/java/org/assertj/core/api/AbstractClassAssert.java
+++ b/assertj-core/src/main/java/org/assertj/core/api/AbstractClassAssert.java
@@ -781,6 +781,16 @@ public abstract class AbstractClassAssert<SELF extends AbstractClassAssert<SELF>
     if (actual.getSuperclass() != null) throw assertionError(shouldHaveNoSuperclass(actual));
   }
 
+  /**
+   * @deprecated use {@link #hasPublicFields(String...)} instead.
+   * @param fields the fields who must be in the class.
+   * @return {@code this} assertions object
+   */
+  @Deprecated
+  public SELF hasFields(String... fields) {
+    return hasPublicFields(fields);
+  }
+
   /**
    * Verifies that the actual {@code Class} has the given accessible public fields (as in {@link Class#getFields()}).
    * <p>
diff --git a/assertj-core/src/main/java/org/assertj/core/api/AbstractCompletableFutureAssert.java b/assertj-core/src/main/java/org/assertj/core/api/AbstractCompletableFutureAssert.java
index 0c6a74ede..82b64828e 100644
--- a/assertj-core/src/main/java/org/assertj/core/api/AbstractCompletableFutureAssert.java
+++ b/assertj-core/src/main/java/org/assertj/core/api/AbstractCompletableFutureAssert.java
@@ -12,21 +12,25 @@
  */
 package org.assertj.core.api;
 
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
 import static org.assertj.core.error.ShouldBeEqual.shouldBeEqual;
 import static org.assertj.core.error.ShouldMatch.shouldMatch;
 import static org.assertj.core.error.future.ShouldBeCancelled.shouldBeCancelled;
 import static org.assertj.core.error.future.ShouldBeCompleted.shouldBeCompleted;
 import static org.assertj.core.error.future.ShouldBeCompletedExceptionally.shouldHaveCompletedExceptionally;
 import static org.assertj.core.error.future.ShouldBeDone.shouldBeDone;
+import static org.assertj.core.error.future.ShouldHaveFailed.shouldHaveFailed;
 import static org.assertj.core.error.future.ShouldNotBeCancelled.shouldNotBeCancelled;
 import static org.assertj.core.error.future.ShouldNotBeCompleted.shouldNotBeCompleted;
 import static org.assertj.core.error.future.ShouldNotBeCompletedExceptionally.shouldNotHaveCompletedExceptionally;
 import static org.assertj.core.error.future.ShouldNotBeDone.shouldNotBeDone;
+import static org.assertj.core.error.future.ShouldNotHaveFailed.shouldNotHaveFailed;
 
 import java.time.Duration;
 import java.util.Objects;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
@@ -319,6 +323,75 @@ public abstract class AbstractCompletableFutureAssert<SELF extends AbstractCompl
     return myself;
   }
 
+  /**
+   * @deprecated
+   * <p>
+   * Combine isCompletedExceptionally with isNotCancelled instead:
+   *
+   * <pre><code class='java'> assertThat(future).isCompletedExceptionally()
+   *                   .isNotCancelled();</code></pre>
+   *
+   * This assertion is deprecated to change the semantics of failed to correspond to {@link CompletableFuture#get()} failing.
+   * <p>
+   * <b>Original javadoc</b>
+   * <p>
+   * Verifies that the {@link CompletableFuture} has completed exceptionally but has not been cancelled,
+   * this assertion is equivalent to:
+   * <pre><code class='java'> assertThat(future).isCompletedExceptionally()
+   *                   .isNotCancelled();</code></pre>
+   * <p>
+   * Assertion will pass :
+   * <pre><code class='java'> CompletableFuture future = new CompletableFuture();
+   * future.completeExceptionally(new RuntimeException());
+   * assertThat(future).hasFailed();</code></pre>
+   *
+   * Assertion will fail :
+   * <pre><code class='java'> CompletableFuture future = new CompletableFuture();
+   * future.cancel(true);
+   * assertThat(future).hasFailed();</code></pre>
+   *
+   * @return this assertion object.
+   */
+  @Deprecated
+  public SELF hasFailed() {
+    isNotNull();
+    if (!(actual.isCompletedExceptionally() && !actual.isCancelled())) throwAssertionError(shouldHaveFailed(actual));
+    return myself;
+  }
+
+  /**
+   * @deprecated
+   * <p>
+   * Use matches with the following combination instead:
+   *
+   * <pre><code class='java'> assertThat(future).matches (f -&gt; f.isNotCompletedExceptionally() {@literal ||} f.isCancelled());</code></pre>
+   *
+   * This assertion is deprecated because its semantic is not obvious.
+   * <p>
+   * <b>Original javadoc</b>
+   * <p>
+   * Verifies that the {@link CompletableFuture} has not failed i.e: incomplete, completed or cancelled.<br>
+   * This is different from {@link #isNotCompletedExceptionally()} as a cancelled future has not failed but is completed exceptionally.
+   * <p>
+   * Assertion will pass :
+   * <pre><code class='java'> CompletableFuture future = new CompletableFuture();
+   * future.cancel(true);
+   * assertThat(future).hasNotFailed();</code></pre>
+   *
+   * Assertion will fail :
+   * <pre><code class='java'> CompletableFuture future = new CompletableFuture();
+   * future.completeExceptionally(new RuntimeException());
+   * assertThat(future).hasNotFailed();</code></pre>
+   *
+   * @return this assertion object.
+   */
+  @Deprecated
+  public SELF hasNotFailed() {
+    isNotNull();
+    if (actual.isCompletedExceptionally() && !actual.isCancelled()) throwAssertionError(shouldNotHaveFailed(actual));
+    return myself;
+  }
+
   /**
    * Waits if necessary for at most the given time for this future to complete, and then returns its result for further assertions.
    * <p>
@@ -462,6 +535,53 @@ public abstract class AbstractCompletableFutureAssert<SELF extends AbstractCompl
     return internalSucceedsWithin(timeout, unit).asInstanceOf(assertFactory);
   }
 
+  /**
+   * @deprecated
+   * <p>
+   * Although not 100% the same, consider using {@link #failsWithin(Duration)} or {@link #failsWithin(long, TimeUnit)} instead:
+   *
+   * <pre><code class='java'> CompletableFuture future = new CompletableFuture();
+   * future.completeExceptionally(new RuntimeException("boom!"));
+   *
+   * assertThat(future).failsWithin(1, TimeUnit.SECONDS)
+   *                   .withThrowableOfType(RuntimeException.class)
+   *                   .withMessage("boom!"); </code></pre>
+   *
+   * This assertion is deprecated because it relies on {@link #hasFailed()} semantics which we want to move away from (they
+   * are not clear!) and to use failure semantics corresponding to {@link CompletableFuture#get()} failing.
+   * <p>
+   * <b>Original javadoc</b>
+   * <p>
+   * Verifies that the {@link CompletableFuture} has completed exceptionally and
+   * returns a Throwable assertion object allowing to check the Throwable that has caused the future to fail.
+   * <p>
+   * Assertion will pass :
+   * <pre><code class='java'> CompletableFuture future = new CompletableFuture();
+   * future.completeExceptionally(new RuntimeException("boom!"));
+   *
+   * assertThat(future).hasFailedWithThrowableThat().isInstanceOf(RuntimeException.class);
+   *                                                .hasMessage("boom!"); </code></pre>
+   *
+   * Assertion will fail :
+   * <pre><code class='java'> CompletableFuture future = new CompletableFuture();
+   * future.completeExceptionally(new RuntimeException());
+   *
+   * assertThat(future).hasFailedWithThrowableThat().isInstanceOf(IllegalArgumentException.class);
+   * </code></pre>
+   *
+   * @return an exception assertion object.
+   */
+  @Deprecated
+  public AbstractThrowableAssert<?, ? extends Throwable> hasFailedWithThrowableThat() {
+    hasFailed();
+    try {
+      actual.join();
+      return assertThat((Throwable) null);
+    } catch (CompletionException e) {
+      return assertThat(e.getCause());
+    }
+  }
+
   /**
    * Checks that the future does not complete within the given time (by calling {@link Future#get(long, TimeUnit)}) and returns
    * the exception that caused the failure for further (exception) assertions, the exception can be any of
diff --git a/assertj-parent/pom.xml b/assertj-parent/pom.xml
index c7438e822..59785003b 100644
--- a/assertj-parent/pom.xml
+++ b/assertj-parent/pom.xml
@@ -16,7 +16,7 @@
 
   <properties>
     <additionalparam>-Xdoclint:none</additionalparam>
-    <java.version>8</java.version>
+    <java.version>17</java.version>
     <maven.compiler.parameters>true</maven.compiler.parameters>
     <maven.compiler.release>${java.version}</maven.compiler.release>
     <maven.compiler.source>${java.version}</maven.compiler.source>


Test patch:
diff --git a/assertj-core/src/main/java9/module-info.java b/assertj-core/src/main/module/module-info.java
similarity index 100%
rename from assertj-core/src/main/java9/module-info.java
rename to assertj-core/src/main/module/module-info.java
diff --git a/assertj-core/src/test/java/org/assertj/core/api/BDDSoftAssertionsTest.java b/assertj-core/src/test/java/org/assertj/core/api/BDDSoftAssertionsTest.java
index 7a29adba3..7c312cc53 100644
--- a/assertj-core/src/test/java/org/assertj/core/api/BDDSoftAssertionsTest.java
+++ b/assertj-core/src/test/java/org/assertj/core/api/BDDSoftAssertionsTest.java
@@ -264,6 +264,7 @@ class BDDSoftAssertionsTest extends BaseAssertionsTest {
     softly.then(OptionalDouble.of(0.0)).isEqualTo(1.0);
     softly.then(OptionalLong.of(0L)).isEqualTo(1L);
     softly.then(URI.create("http://assertj.org")).hasPort(8888);
+    softly.then(CompletableFuture.completedFuture("done")).hasFailed();
     softly.then((Predicate<String>) s -> s.equals("something")).accepts("something else");
     softly.then((IntPredicate) s -> s == 1).accepts(2);
     softly.then((LongPredicate) s -> s == 1).accepts(2);
@@ -282,7 +283,7 @@ class BDDSoftAssertionsTest extends BaseAssertionsTest {
     MultipleFailuresError error = catchThrowableOfType(() -> softly.assertAll(), MultipleFailuresError.class);
     // THEN
     List<String> errors = error.getFailures().stream().map(Object::toString).collect(toList());
-    assertThat(errors).hasSize(61);
+    assertThat(errors).hasSize(62);
     assertThat(errors.get(0)).contains(shouldBeEqualMessage("0", "1"));
     assertThat(errors.get(1)).contains(format("%nExpecting value to be true but was false"));
     assertThat(errors.get(2)).contains(format("%nExpecting value to be true but was false"));
@@ -347,27 +348,28 @@ class BDDSoftAssertionsTest extends BaseAssertionsTest {
     assertThat(errors.get(44)).contains(shouldBeEqualMessage("OptionalDouble[0.0]", "1.0"));
     assertThat(errors.get(45)).contains(shouldBeEqualMessage("OptionalLong[0]", "1L"));
     assertThat(errors.get(46)).contains("Expecting port of");
-    assertThat(errors.get(47)).contains(format("%nExpecting actual:%n  given predicate%n"
-                                               + "to accept \"something else\" but it did not."));
+    assertThat(errors.get(47)).contains("to have failed");
     assertThat(errors.get(48)).contains(format("%nExpecting actual:%n  given predicate%n"
-                                               + "to accept 2 but it did not."));
+                                               + "to accept \"something else\" but it did not."));
     assertThat(errors.get(49)).contains(format("%nExpecting actual:%n  given predicate%n"
-                                               + "to accept 2L but it did not."));
+                                               + "to accept 2 but it did not."));
     assertThat(errors.get(50)).contains(format("%nExpecting actual:%n  given predicate%n"
+                                               + "to accept 2L but it did not."));
+    assertThat(errors.get(51)).contains(format("%nExpecting actual:%n  given predicate%n"
                                                + "to accept 2.0 but it did not."));
-    assertThat(errors.get(51)).contains(format("%nExpecting actual:%n"
+    assertThat(errors.get(52)).contains(format("%nExpecting actual:%n"
                                                + "  <http://assertj.org:80>%n"
                                                + "not to have a port but had:%n"
                                                + "  <80>"));
-    assertThat(errors.get(52)).contains(format("does-not-exist"));
-    assertThat(errors.get(53)).contains(format("2000"));
-    assertThat(errors.get(54)).contains("duration check");
-    assertThat(errors.get(55)).contains("instant check");
-    assertThat(errors.get(56)).contains("ZonedDateTime check");
-    assertThat(errors.get(57)).contains("LocalDateTime check");
-    assertThat(errors.get(58)).contains("LocalDate check");
-    assertThat(errors.get(59)).contains("Spliterator check");
-    assertThat(errors.get(60)).contains("LongAdder check");
+    assertThat(errors.get(53)).contains(format("does-not-exist"));
+    assertThat(errors.get(54)).contains(format("2000"));
+    assertThat(errors.get(55)).contains("duration check");
+    assertThat(errors.get(56)).contains("instant check");
+    assertThat(errors.get(57)).contains("ZonedDateTime check");
+    assertThat(errors.get(58)).contains("LocalDateTime check");
+    assertThat(errors.get(59)).contains("LocalDate check");
+    assertThat(errors.get(60)).contains("Spliterator check");
+    assertThat(errors.get(61)).contains("LongAdder check");
   }
 
   @Test
diff --git a/assertj-core/src/test/java/org/assertj/core/api/BDDSoftAssertions_future_Test.java b/assertj-core/src/test/java/org/assertj/core/api/BDDSoftAssertions_future_Test.java
index a5b97e48e..dbcbc3205 100644
--- a/assertj-core/src/test/java/org/assertj/core/api/BDDSoftAssertions_future_Test.java
+++ b/assertj-core/src/test/java/org/assertj/core/api/BDDSoftAssertions_future_Test.java
@@ -48,6 +48,7 @@ class BDDSoftAssertions_future_Test extends BaseAssertionsTest {
     CompletionStage<String> completionStage = completedFuture("done");
     // WHEN
     softly.then(completionStage).isDone();
+    softly.then(completionStage).hasNotFailed();
     softly.then(completionStage).isCancelled();
     completionStage = null;
     softly.then(completionStage).isNull();
diff --git a/assertj-core/src/test/java/org/assertj/core/api/SoftAssertionsTest.java b/assertj-core/src/test/java/org/assertj/core/api/SoftAssertionsTest.java
index 41c8f45ea..aed974be5 100644
--- a/assertj-core/src/test/java/org/assertj/core/api/SoftAssertionsTest.java
+++ b/assertj-core/src/test/java/org/assertj/core/api/SoftAssertionsTest.java
@@ -296,6 +296,7 @@ class SoftAssertionsTest extends BaseAssertionsTest {
       softly.assertThat(OptionalDouble.of(0.0)).isEqualTo(1.0);
       softly.assertThat(OptionalLong.of(0L)).isEqualTo(1L);
       softly.assertThat(URI.create("http://assertj.org")).hasPort(8888);
+      softly.assertThat(CompletableFuture.completedFuture("done")).hasFailed();
       softly.assertThat((Predicate<String>) s -> s.equals("something")).accepts("something else");
       softly.assertThat((IntPredicate) s -> s == 1).accepts(2);
       softly.assertThat((LongPredicate) s -> s == 1).accepts(2);
@@ -308,7 +309,7 @@ class SoftAssertionsTest extends BaseAssertionsTest {
       fail("Should not reach here");
     } catch (MultipleFailuresError e) {
       List<String> errors = e.getFailures().stream().map(Object::toString).collect(toList());
-      then(errors).hasSize(54);
+      then(errors).hasSize(55);
       then(errors.get(0)).contains(shouldBeEqualMessage("0", "1"));
       then(errors.get(1)).contains(format("%nExpecting value to be true but was false"));
       then(errors.get(2)).contains(format("%nExpecting value to be true but was false"));
@@ -392,24 +393,25 @@ class SoftAssertionsTest extends BaseAssertionsTest {
       then(errors.get(44)).contains(shouldBeEqualMessage("OptionalDouble[0.0]", "1.0"));
       then(errors.get(45)).contains(shouldBeEqualMessage("OptionalLong[0]", "1L"));
       then(errors.get(46)).contains("Expecting port of");
-      then(errors.get(47)).contains(format("%nExpecting actual:%n  given predicate%n"
+      then(errors.get(47)).contains("to have failed");
+      then(errors.get(48)).contains(format("%nExpecting actual:%n  given predicate%n"
                                            + "to accept \"something else\" but it did not."));
 
-      then(errors.get(48)).contains(format("%nExpecting actual:%n  given predicate%n"
+      then(errors.get(49)).contains(format("%nExpecting actual:%n  given predicate%n"
                                            + "to accept 2 but it did not."));
 
-      then(errors.get(49)).contains(format("%nExpecting actual:%n  given predicate%n"
-                                           + "to accept 2L but it did not."));
       then(errors.get(50)).contains(format("%nExpecting actual:%n  given predicate%n"
+                                           + "to accept 2L but it did not."));
+      then(errors.get(51)).contains(format("%nExpecting actual:%n  given predicate%n"
                                            + "to accept 2.0 but it did not."));
-      then(errors.get(51)).contains(format("%nExpecting actual:%n"
+      then(errors.get(52)).contains(format("%nExpecting actual:%n"
                                            + "  <http://assertj.org:80>%n"
                                            + "not to have a port but had:%n"
                                            + "  <80>"));
-      then(errors.get(52)).contains(format("%nExpecting Duration:%n"
+      then(errors.get(53)).contains(format("%nExpecting Duration:%n"
                                            + "  10H%n"
                                            + "to have 5L hours but had 10L"));
-      then(errors.get(53)).contains(format("%nExpecting Period:%n  P1D%nto have 2 days but had 1"));
+      then(errors.get(54)).contains(format("%nExpecting Period:%n  P1D%nto have 2 days but had 1"));
     }
   }
 
diff --git a/assertj-core/src/test/java/org/assertj/core/api/SoftAssertions_future_Test.java b/assertj-core/src/test/java/org/assertj/core/api/SoftAssertions_future_Test.java
index 58f2c2f8c..c2c98fb1d 100644
--- a/assertj-core/src/test/java/org/assertj/core/api/SoftAssertions_future_Test.java
+++ b/assertj-core/src/test/java/org/assertj/core/api/SoftAssertions_future_Test.java
@@ -49,6 +49,7 @@ class SoftAssertions_future_Test extends BaseAssertionsTest {
     CompletionStage<String> completionStage = completedFuture("done");
     // WHEN
     softly.assertThat(completionStage).isDone();
+    softly.assertThat(completionStage).hasNotFailed();
     softly.assertThat(completionStage).isCancelled();
     completionStage = null;
     softly.assertThat(completionStage).isNull();
diff --git a/assertj-core/src/test/java/org/assertj/core/api/charsequence/CharSequenceAssert_isXmlEqualToContentOf_Test.java b/assertj-core/src/test/java/org/assertj/core/api/charsequence/CharSequenceAssert_isXmlEqualToContentOf_Test.java
new file mode 100644
index 000000000..43a4c73ae
--- /dev/null
+++ b/assertj-core/src/test/java/org/assertj/core/api/charsequence/CharSequenceAssert_isXmlEqualToContentOf_Test.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2025 the original author or authors.
+ */
+package org.assertj.core.api.charsequence;
+
+import static org.assertj.core.api.Assertions.contentOf;
+import static org.mockito.Mockito.verify;
+
+import java.io.File;
+
+import org.assertj.core.api.CharSequenceAssert;
+import org.assertj.core.api.CharSequenceAssertBaseTest;
+
+/**
+ * Tests for <code>{@link org.assertj.core.api.CharSequenceAssert#isXmlEqualToContentOf(java.io.File)}</code>.
+ * 
+ * @author Joel Costigliola
+ */
+class CharSequenceAssert_isXmlEqualToContentOf_Test extends CharSequenceAssertBaseTest {
+
+  private File xmlFile = new File("src/test/resources/expected.xml");
+
+  @Override
+  protected CharSequenceAssert invoke_api_method() {
+    return assertions.isXmlEqualToContentOf(xmlFile);
+  }
+
+  @Override
+  protected void verify_internal_effects() {
+    verify(strings).assertXmlEqualsTo(getInfo(assertions), getActual(assertions), contentOf(xmlFile));
+  }
+}
diff --git a/assertj-core/src/test/java/org/assertj/core/api/charsequence/CharSequenceAssert_isXmlEqualTo_Test.java b/assertj-core/src/test/java/org/assertj/core/api/charsequence/CharSequenceAssert_isXmlEqualTo_Test.java
new file mode 100644
index 000000000..769bb0875
--- /dev/null
+++ b/assertj-core/src/test/java/org/assertj/core/api/charsequence/CharSequenceAssert_isXmlEqualTo_Test.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2025 the original author or authors.
+ */
+package org.assertj.core.api.charsequence;
+
+import static org.mockito.Mockito.verify;
+
+import org.assertj.core.api.CharSequenceAssert;
+import org.assertj.core.api.CharSequenceAssertBaseTest;
+
+/**
+ * Tests for <code>{@link org.assertj.core.api.CharSequenceAssert#isXmlEqualTo(CharSequence)}</code>.
+ *
+ * @author Joel Costigliola
+ */
+class CharSequenceAssert_isXmlEqualTo_Test extends CharSequenceAssertBaseTest {
+
+  @SuppressWarnings("deprecation")
+  @Override
+  protected CharSequenceAssert invoke_api_method() {
+    return assertions.isXmlEqualTo("<jedi>yoda</jedi>");
+  }
+
+  @Override
+  protected void verify_internal_effects() {
+    verify(strings).assertXmlEqualsTo(getInfo(assertions), getActual(assertions), "<jedi>yoda</jedi>");
+  }
+}
diff --git a/assertj-core/src/test/java/org/assertj/core/api/classes/ClassAssert_hasPublicFields_Test.java b/assertj-core/src/test/java/org/assertj/core/api/classes/ClassAssert_hasFields_Test.java
similarity index 94%
rename from assertj-core/src/test/java/org/assertj/core/api/classes/ClassAssert_hasPublicFields_Test.java
rename to assertj-core/src/test/java/org/assertj/core/api/classes/ClassAssert_hasFields_Test.java
index 45b9461bd..b00632e3b 100644
--- a/assertj-core/src/test/java/org/assertj/core/api/classes/ClassAssert_hasPublicFields_Test.java
+++ b/assertj-core/src/test/java/org/assertj/core/api/classes/ClassAssert_hasFields_Test.java
@@ -22,7 +22,7 @@ import org.assertj.core.api.ClassAssertBaseTest;
  * 
  * @author William Delanoue
  */
-class ClassAssert_hasPublicFields_Test extends ClassAssertBaseTest {
+class ClassAssert_hasFields_Test extends ClassAssertBaseTest {
 
   @Override
   protected ClassAssert invoke_api_method() {
diff --git a/assertj-core/src/test/java/org/assertj/core/api/future/CompletableFutureAssert_hasFailedWithThrowableThat_Test.java b/assertj-core/src/test/java/org/assertj/core/api/future/CompletableFutureAssert_hasFailedWithThrowableThat_Test.java
new file mode 100644
index 000000000..670a9c854
--- /dev/null
+++ b/assertj-core/src/test/java/org/assertj/core/api/future/CompletableFutureAssert_hasFailedWithThrowableThat_Test.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2025 the original author or authors.
+ */
+package org.assertj.core.api.future;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.error.ShouldBeInstance.shouldBeInstance;
+import static org.assertj.core.error.future.ShouldHaveFailed.shouldHaveFailed;
+import static org.assertj.core.util.AssertionsUtil.assertThatAssertionErrorIsThrownBy;
+import static org.assertj.core.util.FailureMessages.actualIsNull;
+
+import java.util.concurrent.CompletableFuture;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.api.Test;
+
+@SuppressWarnings("deprecation")
+class CompletableFutureAssert_hasFailedWithThrowableThat_Test {
+
+  @Test
+  void should_pass_if_completable_future_has_failed() {
+    // GIVEN
+    CompletableFuture<String> future = new CompletableFuture<>();
+    // WHEN
+    future.completeExceptionally(new RuntimeException("some random error"));
+    // THEN
+    assertThat(future).hasFailedWithThrowableThat()
+                      .isInstanceOf(RuntimeException.class)
+                      .hasMessage("some random error");
+  }
+
+  @Test
+  void should_fail_when_completable_future_is_null() {
+    // GIVEN
+    CompletableFuture<String> future = null;
+    // WHEN
+    ThrowingCallable code = () -> assertThat(future).hasFailedWithThrowableThat();
+    // THEN
+    assertThatAssertionErrorIsThrownBy(code).withMessage(actualIsNull());
+  }
+
+  @Test
+  void should_fail_if_completable_future_has_failed_with_wrong_throwable() {
+    // GIVEN
+    CompletableFuture<String> future = new CompletableFuture<>();
+    RuntimeException exception = new RuntimeException("some random error");
+    future.completeExceptionally(exception);
+    // WHEN
+    ThrowingCallable code = () -> assertThat(future).hasFailedWithThrowableThat().isInstanceOf(IllegalArgumentException.class);
+    // THEN
+    assertThatAssertionErrorIsThrownBy(code).withMessage(shouldBeInstance(exception, IllegalArgumentException.class).create());
+  }
+
+  @Test
+  void should_fail_if_completable_future_is_incomplete() {
+    // GIVEN
+    CompletableFuture<String> future = new CompletableFuture<>();
+    // WHEN
+    ThrowingCallable code = () -> assertThat(future).hasFailedWithThrowableThat();
+    // THEN
+    assertThatAssertionErrorIsThrownBy(code).withMessage(shouldHaveFailed(future).create());
+  }
+
+  @Test
+  void should_fail_if_completable_future_is_completed() {
+    // GIVEN
+    CompletableFuture<String> future = CompletableFuture.completedFuture("done");
+    // WHEN
+    ThrowingCallable code = () -> assertThat(future).hasFailedWithThrowableThat();
+    // THEN
+    assertThatAssertionErrorIsThrownBy(code).withMessage(shouldHaveFailed(future).create());
+  }
+
+  @Test
+  void should_fail_if_completable_future_was_cancelled() {
+    // GIVEN
+    CompletableFuture<String> future = new CompletableFuture<>();
+    future.cancel(true);
+    // WHEN
+    ThrowingCallable code = () -> assertThat(future).hasFailedWithThrowableThat();
+    // THEN
+    assertThatAssertionErrorIsThrownBy(code).withMessage(shouldHaveFailed(future).create());
+  }
+}
diff --git a/assertj-core/src/test/java/org/assertj/core/api/future/CompletableFutureAssert_hasFailed_Test.java b/assertj-core/src/test/java/org/assertj/core/api/future/CompletableFutureAssert_hasFailed_Test.java
new file mode 100644
index 000000000..09945861b
--- /dev/null
+++ b/assertj-core/src/test/java/org/assertj/core/api/future/CompletableFutureAssert_hasFailed_Test.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2025 the original author or authors.
+ */
+package org.assertj.core.api.future;
+
+import static java.util.concurrent.CompletableFuture.completedFuture;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.error.future.ShouldHaveFailed.shouldHaveFailed;
+import static org.assertj.core.util.AssertionsUtil.assertThatAssertionErrorIsThrownBy;
+import static org.assertj.core.util.FailureMessages.actualIsNull;
+
+import java.util.concurrent.CompletableFuture;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.api.Test;
+
+@SuppressWarnings("deprecation")
+class CompletableFutureAssert_hasFailed_Test {
+
+  @Test
+  void should_pass_if_completable_future_has_failed() {
+    // GIVEN
+    CompletableFuture<String> future = new CompletableFuture<>();
+    // WHEN
+    future.completeExceptionally(new RuntimeException());
+    // THEN
+    assertThat(future).hasFailed();
+  }
+
+  @Test
+  void should_fail_when_completable_future_is_null() {
+    // GIVEN
+    CompletableFuture<String> future = null;
+    // WHEN
+    ThrowingCallable code = () -> assertThat(future).hasFailed();
+    // THEN
+    assertThatAssertionErrorIsThrownBy(code).withMessage(actualIsNull());
+  }
+
+  @Test
+  void should_fail_if_completable_future_is_incomplete() {
+    // GIVEN
+    CompletableFuture<String> future = new CompletableFuture<>();
+    // WHEN
+    ThrowingCallable code = () -> assertThat(future).hasFailed();
+    // THEN
+    assertThatAssertionErrorIsThrownBy(code).withMessage(shouldHaveFailed(future).create());
+  }
+
+  @Test
+  void should_fail_if_completable_future_is_completed() {
+    // GIVEN
+    CompletableFuture<String> future = completedFuture("done");
+    // WHEN
+    ThrowingCallable code = () -> assertThat(future).hasFailed();
+    // THEN
+    assertThatAssertionErrorIsThrownBy(code).withMessage(shouldHaveFailed(future).create());
+  }
+
+  @Test
+  void should_fail_if_completable_future_was_cancelled() {
+    // GIVEN
+    CompletableFuture<String> future = new CompletableFuture<>();
+    future.cancel(true);
+    // WHEN
+    ThrowingCallable code = () -> assertThat(future).hasFailed();
+    // THEN
+    assertThatAssertionErrorIsThrownBy(code).withMessage(shouldHaveFailed(future).create());
+  }
+}
diff --git a/assertj-core/src/test/java/org/assertj/core/api/future/CompletableFutureAssert_hasNotFailed_Test.java b/assertj-core/src/test/java/org/assertj/core/api/future/CompletableFutureAssert_hasNotFailed_Test.java
new file mode 100644
index 000000000..7925b374d
--- /dev/null
+++ b/assertj-core/src/test/java/org/assertj/core/api/future/CompletableFutureAssert_hasNotFailed_Test.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2025 the original author or authors.
+ */
+package org.assertj.core.api.future;
+
+import static java.lang.String.format;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.error.future.Warning.WARNING;
+import static org.assertj.core.util.AssertionsUtil.assertThatAssertionErrorIsThrownBy;
+import static org.assertj.core.util.FailureMessages.actualIsNull;
+
+import java.util.concurrent.CompletableFuture;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.api.Test;
+
+@SuppressWarnings("deprecation")
+class CompletableFutureAssert_hasNotFailed_Test {
+
+  @Test
+  void should_pass_if_completable_future_is_incomplete() {
+    // GIVEN
+    CompletableFuture<Object> future = new CompletableFuture<>();
+    // THEN
+    assertThat(future).hasNotFailed();
+  }
+
+  @Test
+  void should_pass_if_completable_future_is_completed() {
+    // GIVEN
+    CompletableFuture<String> future = CompletableFuture.completedFuture("done");
+    // THEN
+    assertThat(future).hasNotFailed();
+  }
+
+  @Test
+  void should_pass_if_completable_future_was_cancelled() {
+    // GIVEN
+    CompletableFuture<String> future = new CompletableFuture<>();
+    // WHEN
+    future.cancel(true);
+    // THEN
+    assertThat(future).hasNotFailed();
+  }
+
+  @Test
+  void should_fail_when_completable_future_is_null() {
+    // GIVEN
+    CompletableFuture<String> future = null;
+    // WHEN
+    ThrowingCallable code = () -> assertThat(future).hasNotFailed();
+    // THEN
+    assertThatAssertionErrorIsThrownBy(code).withMessage(actualIsNull());
+  }
+
+  @Test
+  void should_fail_if_completable_future_has_failed() {
+    // GIVEN
+    CompletableFuture<String> future = new CompletableFuture<>();
+    future.completeExceptionally(new RuntimeException());
+    // WHEN
+    ThrowingCallable code = () -> assertThat(future).hasNotFailed();
+    // THEN
+    assertThatAssertionErrorIsThrownBy(code).withMessageStartingWith(format("%nExpecting%n  <CompletableFuture[Failed with the following stack trace:%njava.lang.RuntimeException"))
+                                            .withMessageEndingWith("to not have failed.%n%s", WARNING);
+
+  }
+}
diff --git a/assertj-tests/assertj-integration-tests/assertj-core-groovy/pom.xml b/assertj-tests/assertj-integration-tests/assertj-core-groovy/pom.xml
index 2d96af731..a4fc2e08f 100644
--- a/assertj-tests/assertj-integration-tests/assertj-core-groovy/pom.xml
+++ b/assertj-tests/assertj-integration-tests/assertj-core-groovy/pom.xml
@@ -16,7 +16,7 @@
     <dependency>
       <groupId>org.apache.groovy</groupId>
       <artifactId>groovy</artifactId>
-      <version>4.0.24</version>
+      <version>4.0.25</version>
       <scope>test</scope>
     </dependency>
     <dependency>
diff --git a/assertj-tests/assertj-integration-tests/assertj-core-kotlin/pom.xml b/assertj-tests/assertj-integration-tests/assertj-core-kotlin/pom.xml
index c4c2ec706..763e1b8dd 100644
--- a/assertj-tests/assertj-integration-tests/assertj-core-kotlin/pom.xml
+++ b/assertj-tests/assertj-integration-tests/assertj-core-kotlin/pom.xml
@@ -13,7 +13,7 @@
   <name>AssertJ Core Integration Tests (Kotlin)</name>
 
   <properties>
-    <kotlin.version>2.1.0</kotlin.version>
+    <kotlin.version>2.1.10</kotlin.version>
   </properties>
 
   <dependencies>
diff --git a/assertj-tests/assertj-integration-tests/assertj-core-tests/pom.xml b/assertj-tests/assertj-integration-tests/assertj-core-tests/pom.xml
index f8a28eef9..e1f7d5323 100644
--- a/assertj-tests/assertj-integration-tests/assertj-core-tests/pom.xml
+++ b/assertj-tests/assertj-integration-tests/assertj-core-tests/pom.xml
@@ -40,7 +40,7 @@
     <dependency>
       <groupId>nl.jqno.equalsverifier</groupId>
       <artifactId>equalsverifier</artifactId>
-      <version>3.18.1</version>
+      <version>3.18.2</version>
       <scope>test</scope>
     </dependency>
     <dependency>
diff --git a/assertj-tests/assertj-integration-tests/assertj-core-tests/src/test/java/org/assertj/tests/core/api/charsequence/CharSequenceAssert_isJavaBlank_Test.java b/assertj-tests/assertj-integration-tests/assertj-core-tests/src/test/java/org/assertj/tests/core/api/charsequence/CharSequenceAssert_isJavaBlank_Test.java
new file mode 100644
index 000000000..1f1cfcb03
--- /dev/null
+++ b/assertj-tests/assertj-integration-tests/assertj-core-tests/src/test/java/org/assertj/tests/core/api/charsequence/CharSequenceAssert_isJavaBlank_Test.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2025 the original author or authors.
+ */
+package org.assertj.tests.core.api.charsequence;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.BDDAssertions.then;
+import static org.assertj.core.error.ShouldBeBlank.shouldBeBlank;
+import static org.assertj.tests.core.util.AssertionsUtil.expectAssertionError;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.NullSource;
+import org.junit.jupiter.params.provider.ValueSource;
+
+/**
+ * @author Filip Hrisafov
+ */
+@SuppressWarnings("deprecation")
+class CharSequenceAssert_isJavaBlank_Test {
+
+  @ParameterizedTest
+  @ValueSource(strings = {
+      " ",
+      "\t", // tab
+      "\n", // line feed
+      "\r", // carriage return
+      " \n\r  "
+  })
+  void should_pass_if_actual_is_blank(String actual) {
+    // WHEN/THEN
+    assertThat(actual).isJavaBlank();
+  }
+
+  @ParameterizedTest
+  @NullSource
+  @ValueSource(strings = {
+      "",
+      "a",
+      " bc ",
+      "\u00A0", // non-breaking space
+      "\u2007", // non-breaking space
+      "\u202F"  // non-breaking space
+  })
+  void should_fail_if_actual_is_not_blank(String actual) {
+    // WHEN
+    AssertionError assertionError = expectAssertionError(() -> assertThat(actual).isJavaBlank());
+    // THEN
+    then(assertionError).hasMessage(shouldBeBlank(actual).create());
+  }
+
+}
diff --git a/assertj-tests/assertj-integration-tests/assertj-core-tests/src/test/java/org/assertj/tests/core/api/charsequence/CharSequenceAssert_isNotJavaBlank_Test.java b/assertj-tests/assertj-integration-tests/assertj-core-tests/src/test/java/org/assertj/tests/core/api/charsequence/CharSequenceAssert_isNotJavaBlank_Test.java
new file mode 100644
index 000000000..e9d582d6f
--- /dev/null
+++ b/assertj-tests/assertj-integration-tests/assertj-core-tests/src/test/java/org/assertj/tests/core/api/charsequence/CharSequenceAssert_isNotJavaBlank_Test.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2025 the original author or authors.
+ */
+package org.assertj.tests.core.api.charsequence;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.BDDAssertions.then;
+import static org.assertj.core.error.ShouldNotBeBlank.shouldNotBeBlank;
+import static org.assertj.tests.core.util.AssertionsUtil.expectAssertionError;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.NullSource;
+import org.junit.jupiter.params.provider.ValueSource;
+
+/**
+ * @author Filip Hrisafov
+ */
+@SuppressWarnings("deprecation")
+class CharSequenceAssert_isNotJavaBlank_Test {
+
+  @ParameterizedTest
+  @NullSource
+  @ValueSource(strings = {
+      "",
+      "a",
+      " bc ",
+      "\u00A0", // non-breaking space
+      "\u2007", // non-breaking space
+      "\u202F"  // non-breaking space
+  })
+  void should_pass_if_actual_is_not_blank(String actual) {
+    // WHEN/THEN
+    assertThat(actual).isNotJavaBlank();
+  }
+
+  @ParameterizedTest
+  @ValueSource(strings = {
+      " ",
+      "\t", // tab
+      "\n", // line feed
+      "\r", // carriage return
+      " \n\r  "
+  })
+  void should_fail_if_actual_is_blank(String actual) {
+    // WHEN
+    AssertionError assertionError = expectAssertionError(() -> assertThat(actual).isNotJavaBlank());
+    // THEN
+    then(assertionError).hasMessage(shouldNotBeBlank(actual).create());
+  }
+
+}