/*
* Copyright 2012-2015 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 org.springframework.hateoas.mvc;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import org.joda.time.DateTime;
import org.joda.time.format.ISODateTimeFormat;
import org.junit.Test;
import org.springframework.core.MethodParameter;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.TestUtils;
import org.springframework.hateoas.mvc.ControllerLinkBuilderUnitTest.ControllerWithMethods;
import org.springframework.hateoas.mvc.ControllerLinkBuilderUnitTest.PersonControllerImpl;
import org.springframework.hateoas.mvc.ControllerLinkBuilderUnitTest.PersonsAddressesController;
import org.springframework.http.HttpEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.util.UriComponentsBuilder;
/**
* Unit tests for {@link ControllerLinkBuilderFactory}.
*
* @author Ricardo Gladwell
* @author Oliver Gierke
* @author Kamill Sokol
* @author Ross Turner
*/
public class ControllerLinkBuilderFactoryUnitTest extends TestUtils {
ControllerLinkBuilderFactory factory = new ControllerLinkBuilderFactory();
@Test
public void createsLinkToControllerRoot() {
Link link = factory.linkTo(PersonControllerImpl.class).withSelfRel();
assertPointsToMockServer(link);
assertThat(link.getRel(), is(Link.REL_SELF));
assertThat(link.getHref(), endsWith("/people"));
}
@Test
public void createsLinkToParameterizedControllerRoot() {
Link link = factory.linkTo(PersonsAddressesController.class, 15).withSelfRel();
assertPointsToMockServer(link);
assertThat(link.getRel(), is(Link.REL_SELF));
assertThat(link.getHref(), endsWith("/people/15/addresses"));
}
@Test
public void appliesParameterValueIfContributorConfigured() {
ControllerLinkBuilderFactory factory = new ControllerLinkBuilderFactory();
factory.setUriComponentsContributors(Arrays.asList(new SampleUriComponentsContributor()));
SpecialType specialType = new SpecialType();
specialType.parameterValue = "value";
Link link = factory.linkTo(methodOn(SampleController.class).sampleMethod(1L, specialType)).withSelfRel();
assertPointsToMockServer(link);
assertThat(link.getHref(), endsWith("/sample/1?foo=value"));
}
/**
* @see #57
*/
@Test
public void usesDateTimeFormatForUriBinding() {
DateTime now = DateTime.now();
ControllerLinkBuilderFactory factory = new ControllerLinkBuilderFactory();
Link link = factory.linkTo(methodOn(SampleController.class).sampleMethod(now)).withSelfRel();
assertThat(link.getHref(), endsWith("/sample/" + ISODateTimeFormat.date().print(now)));
}
/**
* @see #96
*/
@Test
public void linksToMethodWithPathVariableContainingBlank() {
Link link = linkTo(methodOn(ControllerWithMethods.class).methodWithPathVariable("with blank")).withSelfRel();
assertThat(link.getRel(), is(Link.REL_SELF));
assertThat(link.getHref(), endsWith("/something/with%20blank/foo"));
}
/**
* @see #96
*/
@Test
public void createsLinkToParameterizedControllerRootContainingBlank() {
Link link = factory.linkTo(PersonsAddressesController.class, "with blank").withSelfRel();
assertPointsToMockServer(link);
assertThat(link.getRel(), is(Link.REL_SELF));
assertThat(link.getHref(), endsWith("/people/with%20blank/addresses"));
}
/**
* @see #209
*/
@Test
public void createsLinkToControllerMethodWithMapRequestParam() {
Map<String, String> queryParams = new LinkedHashMap<String, String>();
queryParams.put("firstKey", "firstValue");
queryParams.put("secondKey", "secondValue");
Link link = factory.linkTo(methodOn(SampleController.class).sampleMethodWithMap(queryParams)).withSelfRel();
assertPointsToMockServer(link);
assertThat(link.getRel(), is(Link.REL_SELF));
assertThat(link.getHref(), endsWith("/sample/mapsupport?firstKey=firstValue&secondKey=secondValue"));
}
/**
* @see #209
*/
@Test
public void createsLinkToControllerMethodWithMultiValueMapRequestParam() {
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
queryParams.put("key1", Arrays.asList("value1a", "value1b"));
queryParams.put("key2", Arrays.asList("value2a", "value2b"));
Link link = factory.linkTo(methodOn(SampleController.class).sampleMethodWithMap(queryParams)).withSelfRel();
assertPointsToMockServer(link);
assertThat(link.getRel(), is(Link.REL_SELF));
assertThat(link.getHref(),
endsWith("/sample/multivaluemapsupport?key1=value1a&key1=value1b&key2=value2a&key2=value2b"));
}
/**
* @see #372
*/
@Test
public void createsLinkToParameterizedControllerRootWithParameterMap() {
Link link = factory.linkTo(PersonsAddressesController.class, Collections.singletonMap("id", "17")).withSelfRel();
assertPointsToMockServer(link);
assertThat(link.getRel(), is(Link.REL_SELF));
assertThat(link.getHref(), endsWith("/people/17/addresses"));
}
static interface SampleController {
@RequestMapping("/sample/{id}")
HttpEntity<?> sampleMethod(@PathVariable("id") Long id, SpecialType parameter);
@RequestMapping("/sample/{time}")
HttpEntity<?> sampleMethod(@PathVariable("time") @DateTimeFormat(iso = ISO.DATE) DateTime time);
@RequestMapping("/sample/mapsupport")
HttpEntity<?> sampleMethodWithMap(@RequestParam Map<String, String> queryParams);
@RequestMapping("/sample/multivaluemapsupport")
HttpEntity<?> sampleMethodWithMap(@RequestParam MultiValueMap<String, String> queryParams);
}
static class SampleUriComponentsContributor implements UriComponentsContributor {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return SpecialType.class.equals(parameter.getParameterType());
}
@Override
public void enhance(UriComponentsBuilder builder, MethodParameter parameter, Object value) {
builder.queryParam("foo", ((SpecialType) value).parameterValue);
}
}
static class SpecialType {
String parameterValue;
}
}