blob: a00ddd89047c816c426519149ab201afc2ab7486 [file] [log] [blame]
/****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one *
* or more contributor license agreements. See the NOTICE file *
* distributed with this work for additional information *
* regarding copyright ownership. The ASF licenses this file *
* to you 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. *
****************************************************************/
package org.apache.james.jmap.http;
import static io.restassured.RestAssured.given;
import static io.restassured.config.EncoderConfig.encoderConfig;
import static io.restassured.config.RestAssuredConfig.newConfig;
import static org.apache.james.jmap.JMAPUrls.JMAP;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.nio.charset.StandardCharsets;
import org.apache.james.core.Username;
import org.apache.james.jmap.JMAPRoute;
import org.apache.james.jmap.methods.Method;
import org.apache.james.jmap.draft.methods.RequestHandler;
import org.apache.james.jmap.model.InvocationResponse;
import org.apache.james.jmap.methods.ErrorResponse;
import org.apache.james.jmap.model.MethodCallId;
import org.apache.james.mailbox.MailboxSessionUtil;
import org.apache.james.metrics.tests.RecordingMetricFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.netty.handler.codec.http.HttpMethod;
import io.restassured.RestAssured;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.http.ContentType;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.netty.DisposableServer;
import reactor.netty.http.server.HttpServer;
public class JMAPApiRoutesTest {
private static final int RANDOM_PORT = 0;
private DisposableServer server;
private RequestHandler requestHandler;
private Authenticator mockedAuthFilter;
private UserProvisioner mockedUserProvisionner;
@Before
public void setup() throws Exception {
requestHandler = mock(RequestHandler.class);
mockedAuthFilter = mock(Authenticator.class);
mockedUserProvisionner = mock(UserProvisioner.class);
JMAPApiRoutes jmapApiRoutes = new JMAPApiRoutes(requestHandler, new RecordingMetricFactory(),
mockedAuthFilter, mockedUserProvisionner);
JMAPRoute postApiRoute = jmapApiRoutes.routes()
.filter(jmapRoute -> jmapRoute.getEndpoint().getMethod().equals(HttpMethod.POST))
.findFirst()
.get();
server = HttpServer.create()
.port(RANDOM_PORT)
.route(routes -> routes.post(postApiRoute.getEndpoint().getPath(), (req, res) -> postApiRoute.getAction().handleRequest(req, res)))
.bindNow();
RestAssured.requestSpecification = new RequestSpecBuilder()
.setContentType(ContentType.JSON)
.setAccept(ContentType.JSON)
.setConfig(newConfig().encoderConfig(encoderConfig().defaultContentCharset(StandardCharsets.UTF_8)))
.setPort(server.port())
.setBasePath(JMAP)
.build();
doReturn(Mono.just(MailboxSessionUtil.create(Username.of("bob"))))
.when(mockedAuthFilter).authenticate(any());
when(mockedUserProvisionner.provisionUser(any()))
.thenReturn(Mono.empty());
}
@After
public void teardown() {
server.disposeNow();
}
@Test
public void mustReturnBadRequestOnMalformedRequest() {
String missingAnOpeningBracket = "[\"getAccounts\", {\"state\":false}, \"#0\"]]";
given()
.body(missingAnOpeningBracket)
.when()
.post()
.then()
.statusCode(400);
}
@Test
public void mustReturnInvalidArgumentOnInvalidState() throws Exception {
ObjectNode json = new ObjectNode(new JsonNodeFactory(false));
json.put("type", "invalidArgument");
when(requestHandler.handle(any()))
.thenReturn(Flux.just(new InvocationResponse(ErrorResponse.ERROR_METHOD, json, MethodCallId.of("#0"))));
given()
.body("[[\"getAccounts\", {\"state\":false}, \"#0\"]]")
.when()
.post()
.then()
.statusCode(200)
.body(equalTo("[[\"error\",{\"type\":\"invalidArgument\"},\"#0\"]]"));
}
@Test
public void mustReturnAccountsOnValidRequest() throws Exception {
ObjectNode json = new ObjectNode(new JsonNodeFactory(false));
json.put("state", "f6a7e214");
ArrayNode arrayNode = json.putArray("list");
ObjectNode list = new ObjectNode(new JsonNodeFactory(false));
list.put("id", "6asf5");
list.put("name", "roger@barcamp");
arrayNode.add(list);
when(requestHandler.handle(any()))
.thenReturn(Flux.just(new InvocationResponse(Method.Response.name("accounts"), json, MethodCallId.of("#0"))));
given()
.body("[[\"getAccounts\", {}, \"#0\"]]")
.when()
.post()
.then()
.statusCode(200)
.body(equalTo("[[\"accounts\",{" +
"\"state\":\"f6a7e214\"," +
"\"list\":[" +
"{" +
"\"id\":\"6asf5\"," +
"\"name\":\"roger@barcamp\"" +
"}" +
"]" +
"},\"#0\"]]"));
}
}