Skip to content

Commit 555d4a6

Browse files
snicollbclozel
andcommitted
Add AssertJ support for cookies
This commit adds AssertJ compatible assertions for cookies See gh-21178 Co-authored-by: Brian Clozel <[email protected]>
1 parent 1cdbcc5 commit 555d4a6

File tree

2 files changed

+355
-0
lines changed

2 files changed

+355
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*
2+
* Copyright 2002-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.test.web.servlet.assertj;
18+
19+
import java.time.Duration;
20+
import java.util.LinkedHashMap;
21+
import java.util.Map;
22+
import java.util.function.Consumer;
23+
24+
import jakarta.servlet.http.Cookie;
25+
import org.assertj.core.api.AbstractMapAssert;
26+
import org.assertj.core.api.Assertions;
27+
28+
/**
29+
* AssertJ {@link org.assertj.core.api.Assert assertions} that can be applied to
30+
* {@link Cookie cookies}.
31+
*
32+
* @author Brian Clozel
33+
* @author Stephane Nicoll
34+
* @since 6.2
35+
*/
36+
public class CookieMapAssert extends AbstractMapAssert<CookieMapAssert, Map<String, Cookie>, String, Cookie> {
37+
38+
public CookieMapAssert(Cookie[] actual) {
39+
super(mapCookies(actual), CookieMapAssert.class);
40+
as("Cookies");
41+
}
42+
43+
private static Map<String, Cookie> mapCookies(Cookie[] cookies) {
44+
Map<String, Cookie> map = new LinkedHashMap<>();
45+
for (Cookie cookie : cookies) {
46+
map.putIfAbsent(cookie.getName(), cookie);
47+
}
48+
return map;
49+
}
50+
51+
/**
52+
* Verify that the actual cookies contain a cookie with the given {@code name}.
53+
* @param name the name of an expected cookie
54+
* @see #containsKey
55+
*/
56+
public CookieMapAssert containsCookie(String name) {
57+
return containsKey(name);
58+
}
59+
60+
/**
61+
* Verify that the actual cookies contain the cookies with the given
62+
* {@code names}.
63+
* @param names the names of expected cookies
64+
* @see #containsKeys
65+
*/
66+
public CookieMapAssert containsCookies(String... names) {
67+
return containsKeys(names);
68+
}
69+
70+
/**
71+
* Verify that the actual cookies do not contain a cookie with the
72+
* given {@code name}.
73+
* @param name the name of a cookie that should not be present
74+
* @see #doesNotContainKey
75+
*/
76+
public CookieMapAssert doesNotContainCookie(String name) {
77+
return doesNotContainKey(name);
78+
}
79+
80+
/**
81+
* Verify that the actual cookies do not contain any of the cookies with
82+
* the given {@code names}.
83+
* @param names the names of cookies that should not be present
84+
* @see #doesNotContainKeys
85+
*/
86+
public CookieMapAssert doesNotContainCookies(String... names) {
87+
return doesNotContainKeys(names);
88+
}
89+
90+
/**
91+
* Verify that the actual cookies contain a cookie with the given
92+
* {@code name} that satisfy given {@code cookieRequirements}.
93+
* the specified names.
94+
* @param name the name of an expected cookie
95+
* @param cookieRequirements the requirements for the cookie
96+
*/
97+
public CookieMapAssert hasCookieSatisfying(String name, Consumer<Cookie> cookieRequirements) {
98+
return hasEntrySatisfying(name, cookieRequirements);
99+
}
100+
101+
/**
102+
* Verify that the actual cookies contain a cookie with the given
103+
* {@code name} whose {@linkplain Cookie#getValue() value} is equal to the
104+
* given one.
105+
* @param name the name of the cookie
106+
* @param expected the expected value of the cookie
107+
*/
108+
public CookieMapAssert hasValue(String name, String expected) {
109+
return hasCookieSatisfying(name, cookie ->
110+
Assertions.assertThat(cookie.getValue()).isEqualTo(expected));
111+
}
112+
113+
/**
114+
* Verify that the actual cookies contain a cookie with the given
115+
* {@code name} whose {@linkplain Cookie#getMaxAge() max age} is equal to
116+
* the given one.
117+
* @param name the name of the cookie
118+
* @param expected the expected max age of the cookie
119+
*/
120+
public CookieMapAssert hasMaxAge(String name, Duration expected) {
121+
return hasCookieSatisfying(name, cookie ->
122+
Assertions.assertThat(Duration.ofSeconds(cookie.getMaxAge())).isEqualTo(expected));
123+
}
124+
125+
/**
126+
* Verify that the actual cookies contain a cookie with the given
127+
* {@code name} whose {@linkplain Cookie#getPath() path} is equal to
128+
* the given one.
129+
* @param name the name of the cookie
130+
* @param expected the expected path of the cookie
131+
*/
132+
public CookieMapAssert hasPath(String name, String expected) {
133+
return hasCookieSatisfying(name, cookie ->
134+
Assertions.assertThat(cookie.getPath()).isEqualTo(expected));
135+
}
136+
137+
/**
138+
* Verify that the actual cookies contain a cookie with the given
139+
* {@code name} whose {@linkplain Cookie#getDomain() domain} is equal to
140+
* the given one.
141+
* @param name the name of the cookie
142+
* @param expected the expected path of the cookie
143+
*/
144+
public CookieMapAssert hasDomain(String name, String expected) {
145+
return hasCookieSatisfying(name, cookie ->
146+
Assertions.assertThat(cookie.getDomain()).isEqualTo(expected));
147+
}
148+
149+
/**
150+
* Verify that the actual cookies contain a cookie with the given
151+
* {@code name} whose {@linkplain Cookie#getSecure() secure flag} is equal
152+
* to the given one.
153+
* @param name the name of the cookie
154+
* @param expected whether the cookie is secure
155+
*/
156+
public CookieMapAssert isSecure(String name, boolean expected) {
157+
return hasCookieSatisfying(name, cookie ->
158+
Assertions.assertThat(cookie.getSecure()).isEqualTo(expected));
159+
}
160+
161+
/**
162+
* Verify that the actual cookies contain a cookie with the given
163+
* {@code name} whose {@linkplain Cookie#isHttpOnly() http only flag} is
164+
* equal to the given one.
165+
* @param name the name of the cookie
166+
* @param expected whether the cookie is http only
167+
*/
168+
public CookieMapAssert isHttpOnly(String name, boolean expected) {
169+
return hasCookieSatisfying(name, cookie ->
170+
Assertions.assertThat(cookie.isHttpOnly()).isEqualTo(expected));
171+
}
172+
173+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
* Copyright 2002-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.test.web.servlet.assertj;
18+
19+
20+
import java.time.Duration;
21+
import java.util.List;
22+
23+
import jakarta.servlet.http.Cookie;
24+
import org.assertj.core.api.AssertProvider;
25+
import org.junit.jupiter.api.BeforeAll;
26+
import org.junit.jupiter.api.Test;
27+
28+
import static org.assertj.core.api.Assertions.assertThat;
29+
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
30+
31+
/**
32+
* Tests for {@link CookieMapAssert}.
33+
*
34+
* @author Brian Clozel
35+
*/
36+
class CookieMapAssertTests {
37+
38+
static Cookie[] cookies;
39+
40+
@BeforeAll
41+
static void setup() {
42+
Cookie framework = new Cookie("framework", "spring");
43+
framework.setSecure(true);
44+
framework.setHttpOnly(true);
45+
Cookie age = new Cookie("age", "value");
46+
age.setMaxAge(1200);
47+
Cookie domain = new Cookie("domain", "value");
48+
domain.setDomain("spring.io");
49+
Cookie path = new Cookie("path", "value");
50+
path.setPath("/spring");
51+
cookies = List.of(framework, age, domain, path).toArray(new Cookie[0]);
52+
}
53+
54+
@Test
55+
void containsCookieWhenCookieExistsShouldPass() {
56+
assertThat(forCookies()).containsCookie("framework");
57+
}
58+
59+
@Test
60+
void containsCookieWhenCookieMissingShouldFail() {
61+
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
62+
assertThat(forCookies()).containsCookie("missing"));
63+
}
64+
65+
@Test
66+
void containsCookiesWhenCookiesExistShouldPass() {
67+
assertThat(forCookies()).containsCookies("framework", "age");
68+
}
69+
70+
@Test
71+
void containsCookiesWhenCookieMissingShouldFail() {
72+
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
73+
assertThat(forCookies()).containsCookies("framework", "missing"));
74+
}
75+
76+
@Test
77+
void doesNotContainCookieWhenCookieMissingShouldPass() {
78+
assertThat(forCookies()).doesNotContainCookie("missing");
79+
}
80+
81+
@Test
82+
void doesNotContainCookieWhenCookieExistsShouldFail() {
83+
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
84+
assertThat(forCookies()).doesNotContainCookie("framework"));
85+
}
86+
87+
@Test
88+
void doesNotContainCookiesWhenCookiesMissingShouldPass() {
89+
assertThat(forCookies()).doesNotContainCookies("missing", "missing2");
90+
}
91+
92+
@Test
93+
void doesNotContainCookiesWhenAtLeastOneCookieExistShouldFail() {
94+
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
95+
assertThat(forCookies()).doesNotContainCookies("missing", "framework"));
96+
}
97+
98+
@Test
99+
void hasValueEqualsWhenCookieValueMatchesShouldPass() {
100+
assertThat(forCookies()).hasValue("framework", "spring");
101+
}
102+
103+
@Test
104+
void hasValueEqualsWhenCookieValueDiffersShouldFail() {
105+
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
106+
assertThat(forCookies()).hasValue("framework", "other"));
107+
}
108+
109+
@Test
110+
void hasCookieSatisfyingWhenCookieValueMatchesShouldPass() {
111+
assertThat(forCookies()).hasCookieSatisfying("framework", cookie ->
112+
assertThat(cookie.getValue()).startsWith("spr"));
113+
}
114+
115+
@Test
116+
void hasCookieSatisfyingWhenCookieValueDiffersShouldFail() {
117+
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
118+
assertThat(forCookies()).hasCookieSatisfying("framework", cookie ->
119+
assertThat(cookie.getValue()).startsWith("not")));
120+
}
121+
122+
@Test
123+
void hasMaxAgeWhenCookieAgeMatchesShouldPass() {
124+
assertThat(forCookies()).hasMaxAge("age", Duration.ofMinutes(20));
125+
}
126+
127+
@Test
128+
void hasMaxAgeWhenCookieAgeDiffersShouldFail() {
129+
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
130+
assertThat(forCookies()).hasMaxAge("age", Duration.ofMinutes(30)));
131+
}
132+
133+
@Test
134+
void pathWhenCookiePathMatchesShouldPass() {
135+
assertThat(forCookies()).hasPath("path", "/spring");
136+
}
137+
138+
@Test
139+
void pathWhenCookiePathDiffersShouldFail() {
140+
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
141+
assertThat(forCookies()).hasPath("path", "/other"));
142+
}
143+
144+
@Test
145+
void hasDomainWhenCookieDomainMatchesShouldPass() {
146+
assertThat(forCookies()).hasDomain("domain", "spring.io");
147+
}
148+
149+
@Test
150+
void hasDomainWhenCookieDomainDiffersShouldFail() {
151+
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
152+
assertThat(forCookies()).hasDomain("domain", "example.org"));
153+
}
154+
155+
@Test
156+
void isSecureWhenCookieSecureMatchesShouldPass() {
157+
assertThat(forCookies()).isSecure("framework", true);
158+
}
159+
160+
@Test
161+
void isSecureWhenCookieSecureDiffersShouldFail() {
162+
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
163+
assertThat(forCookies()).isSecure("domain", true));
164+
}
165+
166+
@Test
167+
void isHttpOnlyWhenCookieHttpOnlyMatchesShouldPass() {
168+
assertThat(forCookies()).isHttpOnly("framework", true);
169+
}
170+
171+
@Test
172+
void isHttpOnlyWhenCookieHttpOnlyDiffersShouldFail() {
173+
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
174+
assertThat(forCookies()).isHttpOnly("domain", true));
175+
}
176+
177+
178+
private AssertProvider<CookieMapAssert> forCookies() {
179+
return () -> new CookieMapAssert(cookies);
180+
}
181+
182+
}

0 commit comments

Comments
 (0)