package hello.controllers;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.Assert.assertThat;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.embedded.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;
import org.springframework.test.context.junit4.SpringRunner;

import hello.Application;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
@Sql(executionPhase = ExecutionPhase.BEFORE_TEST_METHOD, scripts = "classpath:db/greetings-init.sql")
@ActiveProfiles("test")
public class GreetingControllerIntegrationTest {

	@LocalServerPort
	private int port;

	private URL greeting;
	private URL greetingName;

	private HttpEntity<String> htmlEntity;
	private HttpEntity<String> jsonEntity;

	@Autowired
	private TestRestTemplate template;

	@Before
	public void setUp() throws MalformedURLException {
		String url = "http://localhost:" + port + "/greeting/1";
		this.greeting = new URL(url);
		this.greetingName = new URL(url + "?name=Rob");

		HttpHeaders htmlHeaders = new HttpHeaders();
		htmlHeaders.setAccept(Collections.singletonList(MediaType.TEXT_HTML));
		htmlEntity = new HttpEntity<String>("parameters", htmlHeaders);

		HttpHeaders jsonHeaders = new HttpHeaders();
		jsonHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
		jsonEntity = new HttpEntity<>("parameters", jsonHeaders);
	}

	@Test
	public void getHtmlGreeting() {
		ResponseEntity<String> response = template.exchange(greeting.toString(), HttpMethod.GET, htmlEntity, String.class);
		assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
		assertThat(response.getHeaders().getContentType().toString(), containsString(MediaType.TEXT_HTML_VALUE));
		assertThat(response.getBody(), containsString("Hello, World!"));
	}

	@Test
	public void getJsonGreeting() {
		ResponseEntity<String> response = template.exchange(greeting.toString(), HttpMethod.GET, jsonEntity,
				String.class);
		assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
		assertThat(response.getHeaders().getContentType().toString(), containsString(MediaType.APPLICATION_JSON_VALUE));
		assertThat(response.getBody(), containsString("Hello, World!"));
	}

	@Test
	public void getHtmlGreetingName() {
		ResponseEntity<String> response = template.exchange(greetingName.toString(), HttpMethod.GET, htmlEntity,
				String.class);
		assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
		assertThat(response.getHeaders().getContentType().toString(), containsString(MediaType.TEXT_HTML_VALUE));
		assertThat(response.getBody(), containsString("Hello, Rob!"));
	}

	@Test
	public void getJsonGreetingName() {
		ResponseEntity<String> response = template.exchange(greetingName.toString(), HttpMethod.GET, jsonEntity,
				String.class);
		assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
		assertThat(response.getHeaders().getContentType().toString(), containsString(MediaType.APPLICATION_JSON_VALUE));
		assertThat(response.getBody(), containsString("Hello, Rob!"));
	}
}

@@ -216,29 +216,8 @@
 on;%0A
-import java.net.URL;%0A
 impo
@@ -242,16 +242,16 @@
 ctions;%0A
+
 %0Aimport 
@@ -1647,35 +1647,63 @@
 port;%0A%0A%09private 
-URL
+String baseUrl;%0A%09private String
  greeting;%0A%09priv
@@ -1695,16 +1695,19 @@
 greeting
+Url
 ;%0A%09priva
@@ -1709,19 +1709,22 @@
 private 
-URL
+String
  greetin
@@ -1728,16 +1728,63 @@
 tingName
+Url;%0A%0A%09private static final String INDEX = %22/1%22
 ;%0A%0A%09priv
@@ -1975,16 +1975,18 @@
 %7B%0A%09%09
-String u
+this.baseU
 rl =
@@ -2025,18 +2025,16 @@
 greeting
-/1
 %22;%0A%09%09thi
@@ -2047,58 +2047,71 @@
 ting
- = new URL(url);%0A%09%09this.greetingName = new URL(url
+Url = baseUrl + INDEX;%0A%09%09this.greetingNameUrl = baseUrl + INDEX
  + %22
@@ -2120,17 +2120,16 @@
 ame=Rob%22
-)
 ;%0A%0A%09%09Htt
@@ -2599,35 +2599,27 @@
 nge(greeting
-.toString()
+Url
 , HttpMethod
@@ -2996,27 +2996,19 @@
 greeting
-.toString()
+Url
 , HttpMe
@@ -3020,37 +3020,33 @@
 GET, jsonEntity,
-%0A%09%09%09%09
+ 
 String.class);%0A%09
@@ -3400,35 +3400,27 @@
 greetingName
-.toString()
+Url
 , HttpMethod
@@ -3432,29 +3432,25 @@
  htmlEntity,
-%0A%09%09%09%09
+ 
 String.class
@@ -3803,27 +3803,19 @@
 tingName
-.toString()
+Url
 , HttpMe
@@ -3839,13 +3839,9 @@
 ity,
-%0A%09%09%09%09
+ 
 Stri

Refactor URL generation in the integration tests.