1 package net.avcompris.commons3.web.it.utils;
2
3 import static com.google.common.base.Preconditions.checkState;
4 import static com.google.common.collect.Maps.newHashMap;
5 import static io.restassured.RestAssured.given;
6 import static net.avcompris.commons3.api.tests.ControllerContextUtils.extractControllerContext;
7 import static net.avcompris.commons3.api.tests.TestsSpec.HttpMethod.DELETE;
8 import static net.avcompris.commons3.api.tests.TestsSpec.HttpMethod.GET;
9 import static net.avcompris.commons3.api.tests.TestsSpec.HttpMethod.POST;
10 import static net.avcompris.commons3.api.tests.TestsSpec.HttpMethod.PUT;
11 import static net.avcompris.commons3.web.it.utils.ExpressionUtils.process;
12 import static net.avcompris.commons3.web.it.utils.JSONUtils.parseJSON;
13 import static org.apache.commons.lang3.StringUtils.isBlank;
14 import static org.apache.commons.lang3.StringUtils.substringAfter;
15 import static org.apache.commons.lang3.StringUtils.substringBefore;
16
17 import java.io.IOException;
18 import java.util.Map;
19
20 import javax.annotation.Nullable;
21
22 import org.apache.commons.lang3.NotImplementedException;
23 import org.json.simple.parser.JSONParser;
24 import org.junit.jupiter.api.BeforeEach;
25
26 import com.google.common.collect.ImmutableMap;
27
28 import io.restassured.response.Response;
29 import io.restassured.specification.RequestSpecification;
30 import net.avcompris.commons3.api.tests.AbstractApiTest;
31 import net.avcompris.commons3.api.tests.TestsSpec.AuthenticationSpec;
32 import net.avcompris.commons3.api.tests.TestsSpec.Data;
33 import net.avcompris.commons3.api.tests.TestsSpec.HttpMethod;
34 import net.avcompris.commons3.api.tests.TestsSpec.TestSpec;
35 import net.avcompris.commons3.web.AbstractController;
36
37 public abstract class AbstractWebApiTest extends AbstractApiTest {
38
39 private String baseURL;
40
41 private final Map<Class<? extends AbstractController>, String> moreRestAssured = newHashMap();
42
43 protected AbstractWebApiTest(final TestSpec spec,
44 @Nullable final String superadminAuthorization) {
45
46 super(spec, superadminAuthorization);
47
48 final Class<? extends AbstractWebApiTest> clazz = this.getClass();
49
50 final RestAssured restAssuredAnnotation = clazz.getAnnotation(RestAssured.class);
51
52 checkState(restAssuredAnnotation != null,
53 "Class should be annotated with @RestAssured: %s", clazz.getName());
54
55 try {
56
57 baseURL = process(restAssuredAnnotation.value());
58
59 } catch (final IOException e) {
60
61 throw new RuntimeException(e);
62 }
63 }
64
65 @Override
66 protected final StepExecutionResult execute(final int stepIndex, final StepExecution step) throws Exception {
67
68 final String uri = step.getPath();
69
70 final HttpMethod httpMethod = step.getHttpMethod();
71
72 final String baseURL = moreRestAssured.entrySet().stream()
73
74 .filter(entry -> extractControllerContext(httpMethod, uri, entry.getKey()) != null)
75
76 .map(entry -> entry.getValue())
77
78 .findFirst().orElse(null);
79
80 AbstractWebTest.setUpRestAssured(baseURL != null ? baseURL : this.baseURL);
81
82 final RequestSpecification request = given();
83
84 final AuthenticationSpec authenticationSpec = step.getAuthentication();
85
86 if (authenticationSpec != null) {
87
88 request.header("Authorization", superadminAuthorization);
89 }
90
91 final String path;
92 final Map<String, String> queryParams;
93
94 if (uri.contains("?")) {
95
96 path = substringBefore(uri, "?");
97
98 final String query = substringAfter(uri, "?");
99
100 if (query.contains("&")) {
101 throw new NotImplementedException("uri: " + uri);
102 }
103
104 queryParams = ImmutableMap.<String, String>builder().put(
105 substringBefore(query, "="),
106 substringAfter(query, "=").replace('+', ' ')
107 ).build();
108
109 } else {
110
111 path = uri;
112 queryParams = null;
113 }
114
115 final Response response;
116
117 if (httpMethod == GET) {
118
119 if (queryParams != null) {
120
121 request.queryParams(queryParams);
122 }
123
124 response = request
125
126 .when().get(path);
127
128 } else if (httpMethod == POST) {
129
130 final Map<String, Object> map = newHashMap();
131
132 for (final Data data : step.getData()) {
133
134 map.put(data.getName(), data.getValue());
135 }
136
137 response = request
138
139 .header("Content-Type", "application/json")
140
141 .body(map)
142
143 .when().post(path);
144
145 } else if (httpMethod == PUT) {
146
147 final Map<String, Object> map = newHashMap();
148
149 for (final Data data : step.getData()) {
150
151 map.put(data.getName(), data.getValue());
152 }
153
154 response = request
155
156 .header("Content-Type", "application/json")
157
158 .body(map)
159
160 .when().put(path);
161
162 } else if (httpMethod == DELETE) {
163
164 response = request
165
166 .when().delete(path);
167
168 } else {
169
170 throw new NotImplementedException("httpMethod: " + httpMethod);
171 }
172
173 response.then();
174
175 final int statusCode = response.then().extract().statusCode();
176
177 final String resultAsString = response.then().extract().asString();
178
179 final Class<?> returnType = step.getReturnType();
180
181 final Object dataBean;
182
183 if (returnType == null && isBlank(resultAsString)) {
184
185 dataBean = null;
186
187 } else if (returnType == null) {
188
189 dataBean = new JSONParser().parse(resultAsString);
190
191 } else {
192
193 dataBean = parseJSON(resultAsString, returnType);
194 }
195
196 return new StepExecutionResult(statusCode, dataBean);
197 }
198
199
200
201
202
203
204
205 @BeforeEach
206 public final void setUpRestAssured() throws Exception {
207
208 AbstractWebTest.setUpRestAssured(baseURL);
209 }
210
211 protected final void moreRestAssured(final String expression,
212 final Class<? extends AbstractController> controllerClass0) {
213
214 try {
215
216 moreRestAssured.putIfAbsent(controllerClass0, process(expression));
217
218 } catch (final IOException e) {
219
220 throw new RuntimeException(e);
221 }
222 }
223 }