package com.vtence.molecule; import org.hamcrest.FeatureMatcher; import org.hamcrest.Matcher; import org.hamcrest.Matchers; import org.junit.Test; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Map; import static com.vtence.molecule.http.HeaderNames.CONTENT_TYPE; import static com.vtence.molecule.http.HeaderNames.HOST; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.contains; public class RequestTest { Request request = new Request(); @Test public void maintainsAnOrderedListOfParametersWithSameName() { request.addParameter("letters", "a"); request.addParameter("letters", "b"); request.addParameter("letters", "c"); assertThat("has letters?", request.hasParameter("letters"), equalTo(true)); assertThat("letters", request.parameters("letters"), contains("a", "b", "c")); } @Test public void usesLastSetParameterWhenMultipleParametersWithSameNameExist() { request.addParameter("letter", "a"); request.addParameter("letter", "b"); request.addParameter("letter", "c"); assertThat("authoritative letter", request.parameter("letter"), equalTo("c")); } @Test public void maintainsAListOfParameterNames() { request.addParameter("letters", "a, b, c, etc."); request.addParameter("digits", "1, 2, 3, etc."); request.addParameter("symbols", "#, $, %, etc."); assertThat("parameter names", request.parameterNames(), contains("letters", "digits", "symbols")); } @Test public void removingAParameterRemovesAllParametersWithSameName() { request.addParameter("letters", "a"); request.addParameter("letters", "b"); request.addParameter("letters", "c"); request.addParameter("digits", "1, 2, 3, etc."); request.removeParameter("letters"); assertThat("has letters?", request.hasParameter("letters"), equalTo(false)); assertThat("parameter names", request.parameterNames(), contains("digits")); } @Test public void containsABody() throws IOException { request.body("body"); assertThat("input", request.body(), equalTo("body")); } @Test public void maintainsAnOrderedListOfHeaderNames() throws IOException { request.addHeader("Accept", "text/html"); request.addHeader("Accept", "application/json"); request.header("Accept-Encoding", "gzip"); request.header("Accept-Language", "en"); assertThat("header names", request.headerNames(), contains("Accept", "Accept-Encoding", "Accept-Language")); } @Test public void retrievesHeadersByName() throws IOException { request.header("Accept", "text/html; q=0.9, application/json"); assertThat("header", request.header("Accept"), equalTo("text/html; q=0.9, application/json")); } @Test public void retrievesListOfHeadersWithSameName() throws IOException { request.addHeader("Accept-Language", "en"). addHeader("Accept-Language", "fr"); assertThat("header", request.headers("Accept-Language"), contains("en", "fr")); } @Test public void joinsHeadersWithSameName() throws IOException { request.addHeader("Accept", "text/html; q=0.9"). addHeader("Accept", "application/json"); assertThat("header", request.header("Accept"), equalTo("text/html; q=0.9, application/json")); } @Test public void removesHeaders() throws IOException { request.addHeader("Accept", "text/html"); request.addHeader("Accept-Encoding", "gzip"); assertThat("header?", request.hasHeader("Accept"), equalTo(true)); request.removeHeader("Accept"); assertThat("still there?", request.hasHeader("Accept"), equalTo(false)); assertThat("header names", request.headerNames(), contains("Accept-Encoding")); } @Test public void maintainsAMapOfAttributes() throws IOException { request.attribute("name", "Velociraptor"); request.attribute("family", "Dromaeosauridae"); request.attribute("clade", "Dinosauria"); assertThat("attributes", request.attributes(), allOf(containsEntry("name", "Velociraptor"), containsEntry("family", "Dromaeosauridae"), containsEntry("clade", "Dinosauria"))); assertThat("attribute names", request.attributeKeys(), containsKeys("name", "family", "clade")); } @Test public void removesAttributeOnDemand() throws IOException { request.attribute("name", "Velociraptor"); request.attribute("family", "Dromaeosauridae"); request.attribute("clade", "Dinosauria"); request.removeAttribute("family"); assertThat("attribute names", request.attributeKeys(), containsKeys("name", "clade")); } @Test public void usesISO8859AsDefaultCharset() { assertThat("default charset", request.charset(), equalTo(StandardCharsets.ISO_8859_1)); } @Test public void readsCharsetFromContentType() { request.header(CONTENT_TYPE, "text/html; charset=utf-8"); assertThat("charset", request.charset(), equalTo(StandardCharsets.UTF_8)); } @SuppressWarnings("unchecked") @Test public void maintainsAnOrderedListOfBodyParts() { request.addPart(new BodyPart().name("a")); request.addPart(new BodyPart().name("b")); request.addPart(new BodyPart().name("c")); request.addPart(new BodyPart().name("a")); assertThat("body parts", request.parts(), contains(partWithName("a"), partWithName("b"), partWithName("c"), partWithName("a"))); } @SuppressWarnings("unchecked") @Test public void removesBodyPartsByName() { request.addPart(new BodyPart().name("a")); request.addPart(new BodyPart().name("b")); request.addPart(new BodyPart().name("c")); request.addPart(new BodyPart().name("b")); request.removePart("b"); assertThat("body parts", request.parts(), contains(partWithName("a"), partWithName("c"))); } @Test public void readsHostnameFromHostHeader() { request.serverHost("127.0.0.1"); request.header(HOST, "www.example.com"); assertThat("hostname", request.hostname(), equalTo("www.example.com")); } @Test public void fallbacksToServerHostIfHostHeaderMissing() { request.serverHost("www.example.com"); assertThat("hostname", request.hostname(), equalTo("www.example.com")); } @Test public void readsPortFromHostHeader() { request.serverPort(5432); request.header(HOST, "www.example.com:8080"); assertThat("port", request.port(), equalTo(8080)); } @Test public void knowsSchemeDefaultPort() { request.header(HOST, "www.example.com"); request.scheme("http"); assertThat("http port", request.port(), equalTo(80)); request.scheme("https"); assertThat("https port", request.port(), equalTo(443)); } @Test public void usesServerPortAsFallback() { request.serverPort(5432); assertThat("fallback port", request.port(), equalTo(5432)); } @Test public void usesUriForUrlIfAbsolute() { request.uri("http://www.example.com/over/there?name=ferret"); assertThat("absolute url", request.url(), equalTo("http://www.example.com/over/there?name=ferret")); } @Test public void reconstructsOriginalUrlIfUriIsRelative() { request.uri("/over/there?name=ferret"); request.scheme("http"); request.header(HOST, "www.example.com"); assertThat("using default port", request.url(), equalTo("http://www.example.com/over/there?name=ferret")); request.header(HOST, "www.example.com:8080"); assertThat("using custom port", request.url(), equalTo("http://www.example.com:8080/over/there?name=ferret")); } private Matcher<Iterable<?>> containsKeys(Object... keys) { return Matchers.containsInAnyOrder(keys); } private Matcher<Map<?, ?>> containsEntry(Object key, Object value) { return Matchers.hasEntry(equalTo(key), equalTo(value)); } private Matcher<? super BodyPart> partWithName(String name) { return new FeatureMatcher<BodyPart, String>(equalTo(name), "part named", "name") { @Override protected String featureValueOf(BodyPart actual) { return actual.name(); } }; } }