Skip to content

Commit ed07f96

Browse files
committed
test(cors): simplify CorsIT to only assert presence of headers
Due to our test infrastructure, it's not easy to do assertions on the content of the headers. Also, for the issue fixed in the CORS filter, this test doesn't need to check the content, just make sure they are present.
1 parent 2cac1fe commit ed07f96

1 file changed

Lines changed: 54 additions & 39 deletions

File tree

Lines changed: 54 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
package edu.harvard.iq.dataverse.api;
22

33
import io.restassured.RestAssured;
4-
import io.restassured.response.Response;
5-
import java.util.Arrays;
6-
import java.util.HashSet;
7-
import java.util.List;
8-
import java.util.Locale;
9-
import java.util.Set;
10-
import java.util.stream.Collectors;
114
import org.junit.jupiter.api.BeforeAll;
125
import org.junit.jupiter.params.ParameterizedTest;
136
import org.junit.jupiter.params.provider.ValueSource;
@@ -17,8 +10,6 @@
1710
import static org.hamcrest.Matchers.blankOrNullString;
1811
import static org.hamcrest.Matchers.is;
1912
import static org.hamcrest.Matchers.not;
20-
import static org.junit.jupiter.api.Assertions.assertEquals;
21-
import static org.junit.jupiter.api.Assertions.assertTrue;
2213

2314
/**
2415
* Integration tests for CORS headers on API endpoints. These tests verify that the expected CORS
@@ -30,49 +21,71 @@
3021
* env to `dev_dataverse`.
3122
*/
3223
class CorsIT {
33-
private static final String ORIGIN_NULL = "null";
34-
35-
private final List<String> expectedCorsMethods = List.of("GET", "POST", "PUT", "DELETE", "OPTIONS");
36-
private final List<String> expectedCorsAllowHeaders = List.of("Accept", "Content-Type", "X-Dataverse-key", "Range");
37-
private final List<String> expectedCorsExposeHeaders = List.of("Accept-Ranges", "Content-Range", "Content-Encoding");
38-
3924
@BeforeAll
4025
static void setUp() {
4126
RestAssured.baseURI = UtilIT.getRestAssuredBaseUri();
4227
}
43-
28+
29+
/**
30+
* Tests the presence of CORS preflight headers on various subsystems by sending HTTP OPTIONS requests
31+
* to specified paths and validating the responses for expected headers and status.
32+
* These paths are served by different servlets, filters, and frameworks.
33+
* Nonetheless, any of them should present CORS headers when configured.
34+
*
35+
* <p>
36+
* TODO: Currently, this test relies on the CI infrastructure executing the test to have set at least
37+
* the JVM setting dataverse.cors.origin. Otherwise, no headers will be sent.
38+
* </p>
39+
*
40+
* <p>
41+
* NOTE: At the time of writing (2026-04), there is no infrastructure available to a) manipulate
42+
* these settings in this end-to-end testing scenario nor b) to dynamically reload the test subject.
43+
* It is initialized once at deployment time, which would require isolating this test some other way.
44+
* Thus, only the <i>presence</i> of headers is checked, but not its content
45+
* (which is fine, given the scope of the test).
46+
* </p>
47+
*
48+
* @param path the relative path on the subsystem to which the CORS preflight request is sent
49+
*/
4450
@ParameterizedTest(name = "CORS preflight headers on {0}")
4551
@ValueSource(strings = {
4652
"/api/dataverses/root/datasets",
4753
"/api/v1/dataverses/root/datasets",
4854
"/page_doesnt_exist",
4955
"/dvn/api/data-deposit/v1.1/swordv2/collection/dataverse/root"
5056
})
51-
void testPreflightOptionsCorsHeaders(String path) {
52-
Response response =
53-
given()
54-
.header("Accept", "*/*")
55-
.header("Accept-Language", "en-US,en;q=0.9,es;q=0.8,hu;q=0.7")
56-
.header("Access-Control-Request-Headers", "content-type,x-dataverse-key")
57-
.header("Access-Control-Request-Method", "POST")
58-
.header("Origin", ORIGIN_NULL)
59-
.header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36")
60-
.when()
61-
.options(path)
62-
.then()
63-
.log().ifValidationFails()
64-
.statusCode(anyOf(is(200), is(204)))
65-
.header("Access-Control-Allow-Methods", not(blankOrNullString()))
66-
.header("Access-Control-Allow-Headers", not(blankOrNullString()))
67-
.header("Access-Control-Expose-Headers", not(blankOrNullString()))
68-
.extract()
69-
.response();
70-
71-
assertHeaderSetEquals("Access-Control-Allow-Methods", expectedCorsMethods, response);
72-
assertHeaderSetEquals("Access-Control-Allow-Headers", expectedCorsAllowHeaders, response);
73-
assertHeaderSetEquals("Access-Control-Expose-Headers", expectedCorsExposeHeaders, response);
57+
void ensurePresenceOnDifferentSubsystems(String path) {
58+
given()
59+
.header("Accept", "*/*")
60+
.header("Accept-Language", "en-US,en;q=0.9,es;q=0.8,hu;q=0.7")
61+
.header("Access-Control-Request-Headers", "content-type,x-dataverse-key")
62+
.header("Access-Control-Request-Method", "POST")
63+
.header("Origin", "null")
64+
.header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36")
65+
.when()
66+
.options(path)
67+
.then()
68+
.log().ifValidationFails()
69+
.statusCode(anyOf(is(200), is(204)))
70+
.header("Access-Control-Allow-Methods", not(blankOrNullString()))
71+
.header("Access-Control-Allow-Headers", not(blankOrNullString()))
72+
.header("Access-Control-Expose-Headers", not(blankOrNullString()));
7473
}
74+
75+
/*
76+
The following code may be used in a future test enabling assertions of header contents:
77+
78+
Usage:
79+
assertHeaderSetEquals("Access-Control-Allow-Methods", expectedCorsMethods, response);
80+
assertHeaderSetEquals("Access-Control-Allow-Headers", expectedCorsAllowHeaders, response);
81+
assertHeaderSetEquals("Access-Control-Expose-Headers", expectedCorsExposeHeaders, response);
82+
83+
Class fields:
84+
private final List<String> expectedCorsMethods = List.of("GET", "POST", "PUT", "DELETE", "OPTIONS");
85+
private final List<String> expectedCorsAllowHeaders = List.of("Accept", "Content-Type", "X-Dataverse-key", "Range");
86+
private final List<String> expectedCorsExposeHeaders = List.of("Accept-Ranges", "Content-Range", "Content-Encoding");
7587
88+
Assertions methods:
7689
private static void assertHeaderSetEquals(String headerName, List<String> expectedTokens, Response response) {
7790
String headerValue = response.getHeader(headerName);
7891
assertTrue(headerValue != null && !headerValue.isBlank(), "Missing header: " + headerName);
@@ -93,4 +106,6 @@ private static Set<String> normalizeTokens(String headerValue) {
93106
private static String normalizeToken(String value) {
94107
return value == null ? "" : value.trim().toLowerCase(Locale.ROOT);
95108
}
109+
110+
*/
96111
}

0 commit comments

Comments
 (0)