package endtoend;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.when;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;
import javax.persistence.EntityNotFoundException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation.Builder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.GenericType;
import me.moodcat.backend.UserBackend;
import me.moodcat.backend.rooms.RoomBackend;
import me.moodcat.core.App;
import me.moodcat.database.bootstrapper.Bootstrapper;
import me.moodcat.database.controllers.UserDAO;
import me.moodcat.soundcloud.SoundCloudException;
import me.moodcat.soundcloud.SoundCloudIdentifier;
import me.moodcat.soundcloud.models.MeModel;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.mockito.Matchers;
import org.mockito.Mockito;
import com.google.inject.AbstractModule;
import com.google.inject.Injector;
public abstract class EndToEndTest {
private static App app;
private static UserDAO userDAO;
@BeforeClass
public static void setUpClass() throws Exception {
UserBackend mockedUserBackend = setUpUserBackend();
app = new App(new AbstractModule() {
@Override
protected void configure() {
bind(UserBackend.class).toInstance(mockedUserBackend);
}
});
app.startServer();
final Injector injector = app.getInjector();
// Bootstrap the database
final Bootstrapper bootstrappper = injector.getInstance(Bootstrapper.class);
bootstrappper.parseFromResource("/bootstrap/fall-out-boy.json");
Mockito.when(userDAO.findBySoundcloudId(1337)).thenReturn(bootstrappper.getUser(1));
// Init inserted rooms
final RoomBackend roomBackend = injector.getInstance(RoomBackend.class);
roomBackend.initializeRooms();
}
private static UserBackend setUpUserBackend() throws SoundCloudException {
MeModel meModel = new MeModel();
meModel.setUsername("System");
meModel.setFullName("System");
meModel.setId(1337);
SoundCloudIdentifier identifier = Mockito.mock(SoundCloudIdentifier.class);
Mockito.when(identifier.getMe(Matchers.eq("asdf"))).thenReturn(meModel);
userDAO = Mockito.mock(UserDAO.class);
when(userDAO.findByAccessToken(anyString())).thenThrow(new EntityNotFoundException());
return new UserBackend(() -> userDAO, identifier);
}
@AfterClass
public static void tearDownClass() {
app.stopServer();
}
/**
* Obtain a HTTP-client to start a request.
*
* @return The HTTP-client.
*/
protected Client createClient() {
return ResteasyClientBuilder.newBuilder().build();
}
protected <T> T performGETRequest(final Class<T> clazz, final String endPoint) {
return this.performRequest(endPoint, (response) -> response.get(clazz));
}
protected <T> T performGETRequestWithQueryParameters(final Class<T> clazz,
final String endPoint,
Map<String, Object> queryParameters) {
return this.performRequestWithQueryParams(clazz, endPoint,
(response) -> response.get(clazz), queryParameters);
}
protected <T> T performGETRequestWithGenericType(final GenericType<T> genericType,
final String endPoint) {
return this.performRequest(endPoint, (response) -> response.get(genericType));
}
protected <T> T performPOSTRequest(final Class<T> clazz,
final String endPoint, final Entity<?> postEntity) {
return this.performRequest(endPoint, (response) -> response.post(postEntity, clazz));
}
protected <T> T performPOSTRequestWithQueryParams(Class<T> clazz,
String endPoint, Entity<T> postEntity, Map<String, Object> queryParameters) {
return this.performRequestWithQueryParams(clazz, endPoint,
(response) -> response.post(postEntity, clazz), queryParameters);
}
protected <T> T performRequestWithQueryParams(final Class<T> clazz,
final String endPoint, final Function<Builder, T> callFunction,
final Map<String, Object> queryParameters) {
return this.performRequest(
endPoint,
callFunction,
(target) -> {
WebTarget targetWithParams = target;
for (Entry<String, Object> entry : queryParameters.entrySet()) {
targetWithParams = targetWithParams.queryParam(entry.getKey(),
entry.getValue());
}
return targetWithParams;
});
}
private <T> T performRequest(final String endPoint, final Function<Builder, T> callFunction) {
return this.performRequest(endPoint, callFunction, (target) -> target);
}
private <T> T performRequest(final String endPoint, final Function<Builder, T> callFunction,
final Function<WebTarget, WebTarget> applyQueryParams) {
Client client = this.createClient();
WebTarget target = client.target("http://localhost:8080/api");
target = applyQueryParams.apply(target);
Builder response = target.path(endPoint).request("application/json");
T entity = callFunction.apply(response);
client.close();
return entity;
}
}