2323import  java .util .Arrays ;
2424import  java .util .Collection ;
2525import  java .util .List ;
26+ import  java .util .function .Consumer ;
2627
2728import  org .assertj .core .api .AbstractCollectionAssert ;
2829import  org .assertj .core .api .AbstractObjectAssert ;
2930import  org .assertj .core .api .Assertions ;
3031import  org .assertj .core .api .ObjectAssert ;
31- import  org .assertj .core .presentation .Representation ;
32- import  org .assertj .core .presentation .StandardRepresentation ;
3332
3433import  org .springframework .http .HttpHeaders ;
3534
3837 * {@link HttpHeaders}. 
3938 * 
4039 * @author Stephane Nicoll 
40+  * @author Simon Baslé 
4141 * @since 6.2 
4242 */ 
4343public  class  HttpHeadersAssert  extends  AbstractObjectAssert <HttpHeadersAssert , HttpHeaders > {
@@ -50,15 +50,6 @@ public class HttpHeadersAssert extends AbstractObjectAssert<HttpHeadersAssert, H
5050	public  HttpHeadersAssert (HttpHeaders  actual ) {
5151		super (actual , HttpHeadersAssert .class );
5252		as ("HTTP headers" );
53- 		withRepresentation (new  Representation () {
54- 			@ Override 
55- 			public  String  toStringOf (Object  object ) {
56- 				if  (object  instanceof  HttpHeaders  headers ) {
57- 					return  headers .toString ();
58- 				}
59- 				return  StandardRepresentation .STANDARD_REPRESENTATION .toStringOf (object );
60- 			}
61- 		});
6253		this .namesAssert  = Assertions .assertThat (actual .headerNames ())
6354				.as ("HTTP header names" );
6455	}
@@ -127,7 +118,23 @@ public HttpHeadersAssert doesNotContainHeaders(String... names) {
127118
128119	/** 
129120	 * Verify that the actual HTTP headers contain a header with the given 
130- 	 * {@code name} and {@link String} {@code value}. 
121+ 	 * {@code name} that satisfies the given {@code valueRequirements}. 
122+ 	 * @param name the name of an HTTP header that should not be present 
123+ 	 * @param valueRequirements the group of assertions to run against the 
124+ 	 * values of the header with the given name 
125+ 	 */ 
126+ 	@ SuppressWarnings ("unchecked" )
127+ 	public  HttpHeadersAssert  hasHeaderSatisfying (String  name , Consumer <List <String >> valueRequirements ) {
128+ 		containsHeader (name );
129+ 		Assertions .assertThat (this .actual .get (name ))
130+ 				.as ("check primary value for HTTP header '%s'" , name )
131+ 				.satisfies (values  -> valueRequirements .accept ((List <String >) values ));
132+ 		return  this .myself ;
133+ 	}
134+ 
135+ 	/** 
136+ 	 * Verify that the actual HTTP headers contain a header with the given 
137+ 	 * {@code name} and {@link String} primary {@code value}. 
131138	 * @param name the name of the cookie 
132139	 * @param value the expected value of the header 
133140	 */ 
@@ -141,7 +148,7 @@ public HttpHeadersAssert hasValue(String name, String value) {
141148
142149	/** 
143150	 * Verify that the actual HTTP headers contain a header with the given 
144- 	 * {@code name} and {@link Long} {@code value}. 
151+ 	 * {@code name} and {@link Long} primary  {@code value}. 
145152	 * @param name the name of the cookie 
146153	 * @param value the expected value of the header 
147154	 */ 
@@ -155,7 +162,7 @@ public HttpHeadersAssert hasValue(String name, long value) {
155162
156163	/** 
157164	 * Verify that the actual HTTP headers contain a header with the given 
158- 	 * {@code name} and {@link Instant} {@code value}. 
165+ 	 * {@code name} and {@link Instant} primary  {@code value}. 
159166	 * @param name the name of the cookie 
160167	 * @param value the expected value of the header 
161168	 */ 
@@ -167,6 +174,46 @@ public HttpHeadersAssert hasValue(String name, Instant value) {
167174		return  this .myself ;
168175	}
169176
177+ 	/** 
178+ 	 * Verify that the actual HTTP headers contain a header with the given 
179+ 	 * {@code name} and {@link String} primary {@code value}. 
180+ 	 * <p>This assertion fails if the header has secondary values. 
181+ 	 * @param name the name of the cookie 
182+ 	 * @param value the expected only value of the header 
183+ 	 * @since 7.0 
184+ 	 */ 
185+ 	public  HttpHeadersAssert  hasSingleValue (String  name , String  value ) {
186+ 		doesNotHaveSecondaryValues (name );
187+ 		return  hasValue (name , value );
188+ 	}
189+ 
190+ 	/** 
191+ 	 * Verify that the actual HTTP headers contain a header with the given 
192+ 	 * {@code name} and {@link Long} primary {@code value}. 
193+ 	 * <p>This assertion fails if the header has secondary values. 
194+ 	 * @param name the name of the cookie 
195+ 	 * @param value the expected value of the header 
196+ 	 * @since 7.0 
197+ 	 */ 
198+ 	public  HttpHeadersAssert  hasSingleValue (String  name , long  value ) {
199+ 		doesNotHaveSecondaryValues (name );
200+ 		return  hasValue (name , value );
201+ 	}
202+ 
203+ 	/** 
204+ 	 * Verify that the actual HTTP headers contain a header with the given 
205+ 	 * {@code name} and {@link Instant} primary {@code value}. 
206+ 	 * <p>This assertion fails if the header has secondary values. 
207+ 	 * @param name the name of the cookie 
208+ 	 * @param value the expected value of the header 
209+ 	 * @since 7.0 
210+ 	 */ 
211+ 	public  HttpHeadersAssert  hasSingleValue (String  name , Instant  value ) {
212+ 		doesNotHaveSecondaryValues (name );
213+ 		return  hasValue (name , value );
214+ 	}
215+ 
216+ 
170217	/** 
171218	 * Verify that the given header has a full list of values exactly equal to 
172219	 * the given list of values, and in the same order. 
@@ -224,80 +271,13 @@ public HttpHeadersAssert isNotEmpty() {
224271	 */ 
225272	public  HttpHeadersAssert  hasSize (int  expected ) {
226273		this .namesAssert 
227- 				.as ("check headers have size '%i '" , expected )
274+ 				.as ("check headers have size '%s '" , expected )
228275				.hasSize (expected );
229276		return  this .myself ;
230277	}
231278
232279	/** 
233- 	 * Verify that the number of headers present is strictly greater than the 
234- 	 * given boundary, when considering header names in a case-insensitive 
235- 	 * manner. 
236- 	 * @param boundary the given value to compare actual header size to 
237- 	 */ 
238- 	public  HttpHeadersAssert  hasSizeGreaterThan (int  boundary ) {
239- 		this .namesAssert 
240- 				.as ("check headers have size > '%i'" , boundary )
241- 				.hasSizeGreaterThan (boundary );
242- 		return  this .myself ;
243- 	}
244- 
245- 	/** 
246- 	 * Verify that the number of headers present is greater or equal to the 
247- 	 * given boundary, when considering header names in a case-insensitive 
248- 	 * manner. 
249- 	 * @param boundary the given value to compare actual header size to 
250- 	 */ 
251- 	public  HttpHeadersAssert  hasSizeGreaterThanOrEqualTo (int  boundary ) {
252- 		this .namesAssert 
253- 				.as ("check headers have size >= '%i'" , boundary )
254- 				.hasSizeGreaterThanOrEqualTo (boundary );
255- 		return  this .myself ;
256- 	}
257- 
258- 	/** 
259- 	 * Verify that the number of headers present is strictly less than the 
260- 	 * given boundary, when considering header names in a case-insensitive 
261- 	 * manner. 
262- 	 * @param boundary the given value to compare actual header size to 
263- 	 */ 
264- 	public  HttpHeadersAssert  hasSizeLessThan (int  boundary ) {
265- 		this .namesAssert 
266- 				.as ("check headers have size < '%i'" , boundary )
267- 				.hasSizeLessThan (boundary );
268- 		return  this .myself ;
269- 	}
270- 
271- 	/** 
272- 	 * Verify that the number of headers present is less than or equal to the 
273- 	 * given boundary, when considering header names in a case-insensitive 
274- 	 * manner. 
275- 	 * @param boundary the given value to compare actual header size to 
276- 	 */ 
277- 	public  HttpHeadersAssert  hasSizeLessThanOrEqualTo (int  boundary ) {
278- 		this .namesAssert 
279- 				.as ("check headers have size <= '%i'" , boundary )
280- 				.hasSizeLessThanOrEqualTo (boundary );
281- 		return  this .myself ;
282- 	}
283- 
284- 	/** 
285- 	 * Verify that the number of headers present is between the given boundaries 
286- 	 * (inclusive), when considering header names in a case-insensitive manner. 
287- 	 * @param lowerBoundary the lower boundary compared to which actual size 
288- 	 * should be greater than or equal to 
289- 	 * @param higherBoundary the higher boundary compared to which actual size 
290- 	 * should be less than or equal to 
291- 	 */ 
292- 	public  HttpHeadersAssert  hasSizeBetween (int  lowerBoundary , int  higherBoundary ) {
293- 		this .namesAssert 
294- 				.as ("check headers have size between '%i' and '%i'" , lowerBoundary , higherBoundary )
295- 				.hasSizeBetween (lowerBoundary , higherBoundary );
296- 		return  this .myself ;
297- 	}
298- 
299- 	/** 
300- 	 * Verify that the number actual headers is the same as in the given 
280+ 	 * Verify that the number of actual headers is the same as in the given 
301281	 * {@code HttpHeaders}. 
302282	 * @param other the {@code HttpHeaders} to compare size with 
303283	 * @since 7.0 
@@ -308,4 +288,17 @@ public HttpHeadersAssert hasSameSizeAs(HttpHeaders other) {
308288				.hasSize (other .size ());
309289		return  this .myself ;
310290	}
291+ 
292+ 
293+ 	private  HttpHeadersAssert  doesNotHaveSecondaryValues (String  name ) {
294+ 		containsHeader (name );
295+ 		List <String > values  = this .actual .get (name );
296+ 		int  size  = (values  != null ) ? values .size () : 0 ;
297+ 		Assertions .assertThat (size )
298+ 				.withFailMessage ("Expected HTTP header '%s' to be present "  +
299+ 						"without secondary values, but found <%s> secondary values" , name , size  - 1 )
300+ 				.isOne ();
301+ 		return  this .myself ;
302+ 	}
303+ 
311304}
0 commit comments