/**
* Copyright (C) 2012-2017 the original author or authors.
*
* Licensed 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 ninja;
import com.google.common.collect.ImmutableMap;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;
import ninja.utils.NinjaProperties;
import org.junit.Before;
import org.junit.Test;
import com.google.inject.Injector;
import com.google.inject.Provider;
import java.util.Collections;
import ninja.params.Param;
import ninja.params.ParamParsers;
import ninja.utils.MethodReference;
import ninja.utils.NinjaBaseDirectoryResolver;
import static org.hamcrest.CoreMatchers.is;
import org.mockito.Mockito;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ReverseRouterTest {
Router router;
ReverseRouter reverseRouter;
NinjaProperties ninjaProperties;
NinjaBaseDirectoryResolver ninjaBaseDirectoryResolver;
Injector injector;
Provider<TestController> testControllerProvider;
@Before
@SuppressWarnings("Convert2Lambda")
public void before() {
this.ninjaProperties = mock(NinjaProperties.class);
this.injector = mock(Injector.class);
this.testControllerProvider = mock(Provider.class);
this.ninjaBaseDirectoryResolver = new NinjaBaseDirectoryResolver(ninjaProperties);
when(testControllerProvider.get()).thenReturn(new TestController());
when(injector.getProvider(TestController.class)).thenReturn(testControllerProvider);
when(injector.getInstance(ParamParsers.class)).thenReturn(new ParamParsers(Collections.emptySet()));
Provider<RouteBuilderImpl> routeBuilderImplProvider = mock(Provider.class);
when(routeBuilderImplProvider.get()).thenAnswer((invocation) -> new RouteBuilderImpl(ninjaProperties, ninjaBaseDirectoryResolver));
router = new RouterImpl(injector, ninjaProperties, routeBuilderImplProvider);
reverseRouter = new ReverseRouter(ninjaProperties, router);
router.GET().route("/home").with(TestController::home);
router.GET().route("/user/{email}/{id: .*}").with(TestController::user);
router.GET().route("/u{userId: .*}/entries/{entryId: .*}").with(TestController::entry);
// second route to index should not break reverse routing matching the first
router.GET().route("/home/index").with(TestController::index);
router.compileRoutes();
}
@Test
public void simple() {
String route = reverseRouter.with(TestController::home).build();
assertThat(route, is("/home"));
}
@Test
public void simpleWithMethodReference() {
MethodReference methodRef = new MethodReference(TestController.class, "home");
String route = reverseRouter.with(methodRef).build();
assertThat(route, is("/home"));
}
@Test
public void simpleWithClassReference() {
String route = reverseRouter.with(TestController.class, "home").build();
assertThat(route, is("/home"));
}
@Test
public void simpleWithContext() {
String contextPath = "/context";
when(ninjaProperties.getContextPath()).thenReturn(contextPath);
String route = reverseRouter.with(TestController::home).build();
assertThat(route, is("/context/home"));
}
@Test
public void simpleWithQuery() {
String route = reverseRouter.with(TestController::home)
.queryParam("filter", true)
.queryParam("a", 1L)
.queryParam("foo", "bar")
.queryParam("email", "test@example.com")
.build();
// insertion order retained
assertThat(route, is("/home?filter=true&a=1&foo=bar&email=test%40example.com"));
}
@Test
public void simpleWithRawQuery() {
String route = reverseRouter.with(TestController::home)
.rawQueryParam("email", "test@example.com")
.build();
// insertion order retained
assertThat(route, is("/home?email=test@example.com"));
}
@Test(expected=IllegalArgumentException.class)
public void routeNotFound() {
reverseRouter.with(TestController::notfound)
.build();
}
@Test(expected=IllegalArgumentException.class)
public void simpleNoPathParamsThrowsException() {
reverseRouter.with(TestController::home)
.pathParam("id", 1000000L)
.build();
}
@Test(expected=IllegalArgumentException.class)
public void simpleInvalidPathParamThrowsException() {
reverseRouter.with(TestController::user)
.pathParam("id2", 1000000L)
.build();
}
@Test(expected=IllegalArgumentException.class)
public void simpleMissingAllPathParamThrowsException() {
// param for email missing
reverseRouter.with(TestController::user)
.build();
}
@Test(expected=IllegalArgumentException.class)
public void simpleNotEnoughPathParamThrowsException() {
// param for email missing
reverseRouter.with(TestController::user)
.pathParam("id", 1000000L)
.build();
}
@Test
public void path() {
String route = reverseRouter.with(TestController::user)
.pathParam("email", "test@example.com")
.pathParam("id", 1000000L)
.build();
assertThat(route, is("/user/test%40example.com/1000000"));
}
@Test
public void rawPath() {
String route = reverseRouter.with(TestController::user)
.rawPathParam("email", "test@example.com")
.pathParam("id", 1000000L)
.build();
assertThat(route, is("/user/test@example.com/1000000"));
}
@Test
public void verifySecondRouteMatched() {
String route = reverseRouter.with(TestController::index)
.build();
assertThat(route, is("/home/index"));
}
/**
* A dummy TestController for mocking.
*/
public static class TestController {
private final String message;
public TestController() {
this("not set");
}
public TestController(String message) {
this.message = message;
}
public Result notfound() {
return Results.ok();
}
public Result index() {
return Results.ok();
}
public Result user() {
return Results.ok();
}
public Result entry() {
return Results.ok();
}
public Result ref() {
return Results.ok();
}
public Result home() {
return Results.status(201);
}
public Result message() {
return Results.ok().render(message);
}
public Result status(@Param("status") Integer status) {
return Results.status(status).render(message);
}
public Result exception() throws Exception {
throw new Exception("test");
}
}
}