/* * Copyright 2016 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 io.restassured.response; import io.restassured.function.RestAssuredFunction; import io.restassured.http.ContentType; import io.restassured.matcher.ResponseAwareMatcher; import io.restassured.matcher.RestAssuredMatchers; import io.restassured.parsing.Parser; import io.restassured.specification.Argument; import io.restassured.specification.ResponseSpecification; import org.hamcrest.Matcher; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; /** * A validatable response of a request made by REST Assured. * <p> * Usage example: * <pre> * get("/lotto").then().body("lotto.lottoId", is(5)); * </pre> * </p> */ public interface ValidatableResponseOptions<T extends ValidatableResponseOptions<T, R>, R extends ResponseBody<R> & ResponseOptions<R>> { /** * Validate that the response content conforms to one or more Hamcrest matchers. E.g. * <pre> * // Validate that the response content (body) contains the string "winning-numbers" * get("/lotto").then().content(containsString("winning-numbers")); * * // Validate that the response content (body) contains the string "winning-numbers" and "winners" * get("/lotto").then().assertThat().content(containsString("winning-numbers"), containsString("winners")); * </pre> * * @param matcher The hamcrest matcher that must response content must match. * @param additionalMatchers Optionally additional hamcrest matchers that must return <code>true</code>. * @return the response specification */ T content(Matcher<?> matcher, Matcher<?>... additionalMatchers); /** * This as special kind of validation that is mainly useful when you've specified a root path with an argument placeholder. * For example: * <pre> * get(..).then().assertThat(). * root("x.%s"). // Root path with a placeholder * content(withArgs("firstName"), equalTo(..)). * content(withArgs("lastName"), equalTo(..)). * </pre> * <p/> * Note that this is the same as doing: * <pre> * get(..).then().assertThat(). * root("x.%s"). // Root path with a placeholder * body(withArgs("firstName"), equalTo(..)). * body(withArgs("lastName"), equalTo(..)). * </pre> * <p/> * <p> * Note that this method is the same as {@link #body(java.util.List, org.hamcrest.Matcher, Object...)} but with a method name. * </p> * * @param arguments The arguments to apply to the root path. * @param matcher The hamcrest matcher that must response body must match. * @param additionalKeyMatcherPairs Optionally additional hamcrest matchers that must return <code>true</code>. * @return the response specification * @see #body(String, org.hamcrest.Matcher, Object...) */ T content(List<Argument> arguments, Matcher matcher, Object... additionalKeyMatcherPairs); /** * Compare a path in the response body to something available in the response using arguments when root path is used. * For example imagine that a resource "/x" returns the following JSON document: * <pre> * { * "data" : { * "user1" : { * "userId" : "my-id1", * "href" : "http://localhost:8080/my-id1" * }, * "user2" : { * "userId" : "my-id2", * "href" : "http://localhost:8080/my-id2" * }, * } * } * </pre> * you can then verify the href using: * <pre> * when(). * get("/x"). * then(). * root("data.%s"). * content(withArgs("user1"), new ResponseAwareMatcher<Response>() { * public Matcher<?> matcher(Response response) { * return equalTo("http://localhost:8080/" + response.path("userId")); * } * }); * </pre> * Note that you can also use some of the predefined methods in {@link RestAssuredMatchers}. * <p> * Note that this method is the same as {@link #body(java.util.List, ResponseAwareMatcher)} expect for syntactic differences. * </p> * * @param responseAwareMatcher The {@link ResponseAwareMatcher} that creates the Hamcrest matcher. * @return the response specification * @see #content(String, ResponseAwareMatcher) * @see RestAssuredMatchers#endsWithPath(String) * @see RestAssuredMatchers#startsWithPath(String) * @see RestAssuredMatchers#containsPath(String) * @see RestAssuredMatchers#equalToPath(String) */ T content(List<Argument> arguments, ResponseAwareMatcher<R> responseAwareMatcher); /** * Validate that the JSON or XML response content conforms to one or more Hamcrest matchers.<br> * <h3>JSON example</h3> * <p> * Assume that a GET request to "/lotto" returns a JSON response containing: * <pre> * { "lotto":{ * "lottoId":5, * "winning-numbers":[2,45,34,23,7,5,3], * "winners":[{ * "winnerId":23, * "numbers":[2,45,34,23,3,5] * },{ * "winnerId":54, * "numbers":[52,3,12,11,18,22] * }] * }} * </pre> * <p/> * You can verify that the lottoId is equal to 5 like this: * <pre> * get("/lotto").then().assertThat().content("lotto.lottoId", equalTo(5)); * </pre> * <p/> * You can also verify that e.g. one of the the winning numbers is 45. * <pre> * get("/lotto").then().content("lotto.winning-numbers", hasItem(45)); * </pre> * <p/> * Or both at the same time: * <pre> * get("/lotto").then().content("lotto.lottoId", equalTo(5)).and().content("lotto.winning-numbers", hasItem(45)); * </pre> * <p/> * or a slightly short version: * <pre> * get("/lotto").then().content("lotto.lottoId", equalTo(5), "lotto.winning-numbers", hasItem(45)); * </pre> * </p> * <h3>XML example</h3> * <p> * Assume that a GET request to "/xml" returns a XML response containing: * <pre> * <greeting> * <firstName>John</firstName> * <lastName>Doe</lastName> * </greeting> * </pre> * </p> * <p/> * You can now verify that the firstName is equal to "John" like this: * <pre> * get("/xml").then().content("greeting.firstName", equalTo("John")); * </pre> * <p/> * To verify both the first name and last name you can do like this: * <pre> * get("/xml").then().content("greeting.firstName", equalTo("John")).and().content("greeting.lastName", equalTo("Doe")); * </pre> * <p/> * Or the slightly shorter version of: * <pre> * get("/xml").then().content("greeting.firstName", equalTo("John"), "greeting.lastName", equalTo("Doe")); * </pre> * <h3>Notes</h3> * <p> * Note that if the response content type is not of type <tt>application/xml</tt> or <tt>application/json</tt> you * <i>cannot</i> use this verification. * </p> * <p/> * <p> * The only difference between the <code>content</code> and <code>body</code> methods are of syntactic nature. * </p> * * @param matcher The hamcrest matcher that must response content must match. * @param additionalKeyMatcherPairs Optionally additional hamcrest matchers that must return <code>true</code>. * @return the response specification */ T content(String key, Matcher<?> matcher, Object... additionalKeyMatcherPairs); /** * Same as {@link #body(String, org.hamcrest.Matcher, Object...)} expect that you can pass arguments to the key. This * is useful in situations where you have e.g. pre-defined variables that constitutes the key: * <pre> * String someSubPath = "else"; * int index = 1; * get("/x").then().body("something.%s[%d]", withArgs(someSubPath, index), equalTo("some value")). .. * </pre> * <p/> * or if you have complex root paths and don't wish to duplicate the path for small variations: * <pre> * get("/x").then(). * root("filters.filterConfig[%d].filterConfigGroups.find { it.name == 'Gold' }.includes"). * body(withArgs(0), hasItem("first")). * body(withArgs(1), hasItem("second")). * .. * </pre> * <p/> * The key and arguments follows the standard <a href="http://download.oracle.com/javase/1,5.0/docs/api/java/util/Formatter.html#syntax">formatting syntax</a> of Java. * <p> * Note that <code>withArgs</code> can be statically imported from the <code>io.restassured.RestAssured</code> class. * </p> * * @param path The body path * @param arguments The arguments to apply to the key * @param matcher The hamcrest matcher that must response body must match. * @param additionalKeyMatcherPairs Optionally additional hamcrest matchers that must return <code>true</code>. * @return the response specification * @see #body(String, org.hamcrest.Matcher, Object...) */ T body(String path, List<Argument> arguments, Matcher matcher, Object... additionalKeyMatcherPairs); /** * This as special kind of expectation that is mainly useful when you've specified a root path with an argument placeholder. * For example: * <pre> * get(..).then(). * root("x.%s"). // Root path with a placeholder * body(withArgs("firstName"), equalTo(..)). * body(withArgs("lastName"), equalTo(..)). * </pre> * <p/> * Note that this is the same as doing: * <pre> * get(..).then(). * root("x.%s"). // Root path with a placeholder * content(withArgs("firstName"), equalTo(..)). * content(withArgs("lastName"), equalTo(..)). * </pre> * <p/> * <p> * Note that this method is the same as {@link #content(java.util.List, org.hamcrest.Matcher, Object...)} but with a method name. * </p> * * @param arguments The arguments to apply to the root path. * @param matcher The hamcrest matcher that must response body must match. * @param additionalKeyMatcherPairs Optionally additional hamcrest matchers that must return <code>true</code>. * @return the response specification * @see #body(String, org.hamcrest.Matcher, Object...) */ T body(List<Argument> arguments, Matcher matcher, Object... additionalKeyMatcherPairs); /** * Compare a path in the response body to something available in the response using arguments when root path is used. * For example imagine that a resource "/x" returns the following JSON document: * <pre> * { * "data" : { * "user1" : { * "userId" : "my-id1", * "href" : "http://localhost:8080/my-id1" * }, * "user2" : { * "userId" : "my-id2", * "href" : "http://localhost:8080/my-id2" * }, * } * } * </pre> * you can then verify the href using: * <pre> * when(). * get("/x"). * then(). * root("data.%s"). * body(withArgs("user1"), new ResponseAwareMatcher<Response>() { * public Matcher<?> matcher(Response response) { * return equalTo("http://localhost:8080/" + response.path("userId")); * } * }); * </pre> * Note that you can also use some of the predefined methods in {@link RestAssuredMatchers}. * <p> * Note that this method is the same as {@link #content(java.util.List, ResponseAwareMatcher)} expect for syntactic differences. * </p> * * @param responseAwareMatcher The {@link ResponseAwareMatcher} that creates the Hamcrest matcher. * @return the response specification * @see #body(String, ResponseAwareMatcher) * @see RestAssuredMatchers#endsWithPath(String) * @see RestAssuredMatchers#startsWithPath(String) * @see RestAssuredMatchers#containsPath(String) * @see RestAssuredMatchers#equalToPath(String) */ T body(List<Argument> arguments, ResponseAwareMatcher<R> responseAwareMatcher); /** * Validate that the response status code matches the given Hamcrest matcher. E.g. * <pre> * get("/something").then().assertThat().statusCode(equalTo(200)); * </pre> * * @param expectedStatusCode The expected status code matcher. * @return the response specification */ T statusCode(Matcher<? super Integer> expectedStatusCode); /** * Validate that the response status code matches an integer. E.g. * <pre> * get("/something").then().assertThat().statusCode(200); * </pre> * <p/> * This is the same as: * <pre> * get("/something").then().assertThat().statusCode(equalTo(200)); * </pre> * * @param expectedStatusCode The expected status code. * @return the response specification */ T statusCode(int expectedStatusCode); /** * Validate that the response status line matches the given Hamcrest matcher. E.g. * <pre> * expect().statusLine(equalTo("No Content")).when().get("/something"); * </pre> * * @param expectedStatusLine The expected status line matcher. * @return the response specification */ T statusLine(Matcher<? super String> expectedStatusLine); /** * Validate that the response status line matches the given String. E.g. * <pre> * expect().statusLine("No Content").when().get("/something"); * </pre> * <p/> * This is the same as: * <pre> * expect().statusLine(equalTo("No Content")).when().get("/something"); * </pre> * * @param expectedStatusLine The expected status line. * @return the response specification */ T statusLine(String expectedStatusLine); /** * Validate that response headers matches those specified in a Map. * <p> * E.g. expect that the response of the GET request to "/something" contains header <tt>headerName1=headerValue1</tt> * and <tt>headerName2=headerValue2</tt>: * <pre> * Map expectedHeaders = new HashMap(); * expectedHeaders.put("headerName1", "headerValue1")); * expectedHeaders.put("headerName2", "headerValue2"); * * get("/something").then().assertThat().headers(expectedHeaders); * </pre> * </p> * <p/> * <p> * You can also use Hamcrest matchers: * <pre> * Map expectedHeaders = new HashMap(); * expectedHeaders.put("Content-Type", containsString("charset=UTF-8")); * expectedHeaders.put("Content-Length", "160"); * * get("/something").then().assertThat().headers(expectedHeaders); * </pre> * </p> * * @param expectedHeaders The Map of expected response headers * @return the response specification */ T headers(Map<String, ?> expectedHeaders); /** * Validate that response headers matches the supplied headers and values. * <p> * E.g. expect that the response of the GET request to "/something" contains header <tt>Pragma=no-cache</tt> * and <tt>Content-Encoding=gzip</tt>: * <pre> * get("/something").then().assertThat().headers("Pragma", "no-cache", "Content-Encoding", "gzip"); * </pre> * </p> * <p/> * <p> * You can also use Hamcrest matchers: * <pre> * get("/something").then().assertThat().headers("Content-Type", containsString("application/json"), "Pragma", equalsTo("no-cache")); * </pre> * <p/> * and you can even mix string matching and hamcrest matching: * <pre> * get("/something").then().assertThat().headers("Content-Type", containsString("application/json"), "Pragma", "no-cache"); * </pre> * </p> * * @param firstExpectedHeaderName The name of the first header * @param firstExpectedHeaderValue The value of the first header * @param expectedHeaders A list of expected "header name" - "header value" pairs. * @return the response specification */ T headers(String firstExpectedHeaderName, Object firstExpectedHeaderValue, Object... expectedHeaders); /** * Validate that a response header matches the supplied header name and hamcrest matcher. * <p> * E.g. expect that the response of the GET request to "/something" contains header <tt>Pragma=no-cache</tt>: * <pre> * get("/something").then().assertThat().header("Pragma", containsString("no")); * </pre> * </p> * <p/> * <p> * You can also expect several headers: * <pre> * get("/something").then().assertThat().header("Pragma", equalsTo("no-cache")).and().header("Content-Encoding", containsString("zip")); * </pre> * Also take a look at {@link #headers(String, Object, Object...)} )} for a short version of passing multiple headers. * </p> * * @param headerName The name of the expected header * @param expectedValueMatcher The Hamcrest matcher that must conform to the value * @return the response specification */ T header(String headerName, Matcher<?> expectedValueMatcher); /** * Compare a header in the response to something else available in the response. * <p> * For example imagine that a POST to resource "/x" returns "201 Created" and sets a Location header * that should end with "/x/{id}" where <code>{id}</code> is present in the response body: * <pre> * { "id" : 5 } * </pre> * To verify that the Location header ends with "/x/{id}" you can do like this: * <p> * <pre> * given().param("id", 1).body(..).post("/x").then().assertThat().header("Location", response -> response.endsWith("/x/") + response.path("id")); * </pre> * </p> * <p/> * <p> * </p> * * @param headerName The name of the expected header * @param expectedValueMatcher The Hamcrest matcher that must conform to the value * @return the response specification */ T header(String headerName, ResponseAwareMatcher<R> expectedValueMatcher); /** * Expect that a response header matches the supplied header name and hamcrest matcher using a mapping function. * <p> * E.g. expect that the response of the GET request to "/something" contains header <tt>Content-Length: 500</tt> and you want to * validate that the length must always be less than 600: * <pre> * when(). * get("/something"). * then(). * header("Content-Length", Integer::parseInt, lessThan(600)); * </pre> * </p> * * @param headerName The name of the expected header * @param mappingFunction Map the header to another value type before exposing it to the Hamcrest matcher * @param expectedValueMatcher The Hamcrest matcher that must conform to the value * @return the response specification */ <V> T header(String headerName, RestAssuredFunction<String, V> mappingFunction, Matcher<? super V> expectedValueMatcher); /** * Validate that a response header matches the supplied name and value. * <p> * E.g. expect that the response of the GET request to "/something" contains header <tt>Pragma=no-cache</tt>: * <pre> * get("/something").then().assertThat().header("Pragma", "no-cache"); * </pre> * </p> * <p/> * <p> * You can also expect several headers: * <pre> * get("/something").then().assertThat().header("Pragma", "no-cache").and().header("Content-Encoding", "gzip"); * </pre> * Also take a look at {@link #headers(String, Object, Object...)} for a short version of passing multiple headers. * </p> * * @param headerName The name of the expected header * @param expectedValue The value of the expected header * @return the response specification */ T header(String headerName, String expectedValue); /** * Validate that response cookies matches those specified in a Map. * <p> * E.g. expect that the response of the GET request to "/something" contains cookies <tt>cookieName1=cookieValue1</tt> * and <tt>cookieName2=cookieValue2</tt>: * <pre> * Map expectedCookies = new HashMap(); * expectedCookies.put("cookieName1", "cookieValue1")); * expectedCookies.put("cookieName2", "cookieValue2"); * * get("/something").then().assertThat().cookies(expectedCookies); * </pre> * </p> * <p/> * <p> * You can also use Hamcrest matchers: * <pre> * Map expectedCookies = new HashMap(); * expectedCookies.put("cookieName1", containsString("Value1")); * expectedCookies.put("cookieName2", "cookieValue2"); * * get("/something").then().assertThat().cookies(expectedCookies); * </pre> * </p> * * @param expectedCookies A Map of expected response cookies * @return the response specification */ T cookies(Map<String, ?> expectedCookies); /** * Validate that a cookie exist in the response, regardless of value (it may have no value at all). * * @param cookieName the cookie to validate that it exists * @return the response specification */ T cookie(String cookieName); /** * Validate that response cookies matches the supplied cookie names and values. * <p> * E.g. expect that the response of the GET request to "/something" contains cookies <tt>cookieName1=cookieValue1</tt> * and <tt>cookieName2=cookieValue2</tt>: * <pre> * get("/something").then().assertThat().cookies("cookieName1", "cookieValue1", "cookieName2", "cookieValue2"); * </pre> * </p> * <p/> * <p> * You can also use Hamcrest matchers: * <pre> * get("/something").then().assertThat().cookies("cookieName1", containsString("Value1"), "cookieName2", equalsTo("cookieValue2")); * </pre> * <p/> * and you can even mix string matching and hamcrest matching: * <pre> * get("/something").then().assertThat().cookies("cookieName1", containsString("Value1"), "cookieName2", "cookieValue2"); * </pre> * </p> * * @param firstExpectedCookieName The name of the first cookie * @param firstExpectedCookieValue The value of the first cookie * @param expectedCookieNameValuePairs A list of expected "cookie name" - "cookie value" pairs. * @return the response specification */ T cookies(String firstExpectedCookieName, Object firstExpectedCookieValue, Object... expectedCookieNameValuePairs); /** * Validate that a response cookie matches the supplied cookie name and hamcrest matcher. * <p> * E.g. expect that the response of the GET request to "/something" contain cookie <tt>cookieName1=cookieValue1</tt> * <pre> * get("/something").then().assertThat().cookie("cookieName1", containsString("Value1")); * </pre> * </p> * <p/> * <p> * You can also expect several cookies: * <pre> * get("/something").then().assertThat().cookie("cookieName1", equalsTo("cookieValue1")).and().cookie("cookieName2", containsString("Value2")); * </pre> * Also take a look at {@link #cookies(String, Object, Object...)} for a short version of passing multiple cookies. * </p> * * @param cookieName The name of the expected cookie * @param expectedValueMatcher The Hamcrest matcher that must conform to the value * @return the response specification */ T cookie(String cookieName, Matcher<?> expectedValueMatcher); /** * Validate that a response cookie matches the supplied name and value. * <p> * E.g. expect that the response of the GET request to "/something" contain cookie <tt>cookieName1=cookieValue1</tt>: * <pre> * get("/something").then().assertThat().cookie("cookieName1", "cookieValue1"); * </pre> * </p> * <p/> * <p> * You can also expect several cookies: * <pre> * get("/something").then().assertThat().cookie("cookieName1", "cookieValue1").and().cookie("cookieName2", "cookieValue2"); * </pre> * Also take a look at {@link #cookies(String, Object, Object...)} for a short version of passing multiple cookies. * </p> * * @param cookieName The name of the expected cookie * @param expectedValue The value of the expected cookie * @return the response specification */ T cookie(String cookieName, Object expectedValue); /** * Set the root path of the response body so that you don't need to write the entire path for each expectation. * E.g. instead of writing: * <p/> * <pre> * get(..).then(). * body("x.y.firstName", is(..)). * body("x.y.lastName", is(..)). * body("x.y.age", is(..)). * body("x.y.gender", is(..)). * </pre> * <p/> * you can use a root path and do: * <pre> * get(..).then(). * rootPath("x.y"). * body("firstName", is(..)). * body("lastName", is(..)). * body("age", is(..)). * body("gender", is(..)); * </pre> * <p/> * Note that this method is exactly the same as {@link #root(String)}. * * @param rootPath The root path to use. */ T rootPath(String rootPath); /** * Set the root path with arguments of the response body so that you don't need to write the entire path for each expectation. * <p/> * Note that this method is exactly the same as {@link #root(String, java.util.List)}. * * @param rootPath The root path to use. * @param arguments A list of arguments. The path and arguments follows the standard <a href="http://download.oracle.com/javase/1,5.0/docs/api/java/util/Formatter.html#syntax">formatting syntax</a> of Java. * @see #rootPath(String) */ T rootPath(String rootPath, List<Argument> arguments); /** * Set the root path with arguments of the response body so that you don't need to write the entire path for each expectation. * <p/> * Note that this method is exactly the same as {@link #rootPath(String, java.util.List)}. * * @param rootPath The root path to use. * @param arguments The list of substitution arguments. The path and arguments follows the standard <a href="http://download.oracle.com/javase/1,5.0/docs/api/java/util/Formatter.html#syntax">formatting syntax</a> of Java.. * @see #rootPath(String) */ T root(String rootPath, List<Argument> arguments); /** * Set the root path of the response body so that you don't need to write the entire path for each expectation. * E.g. instead of writing: * <p/> * <pre> * get(..).then(). * body("x.y.firstName", is(..)). * body("x.y.lastName", is(..)). * body("x.y.age", is(..)). * body("x.y.gender", is(..)); * </pre> * <p/> * you can use a root and do: * <pre> * get(..).then(). * root("x.y"). * body("firstName", is(..)). * body("lastName", is(..)). * body("age", is(..)). * body("gender", is(..)). * </pre> * <p/> * Note that this method is exactly the same as {@link #rootPath(String)} but slightly shorter. * * @param rootPath The root path to use. */ T root(String rootPath); /** * Reset the root path of the response body so that you don't need to write the entire path for each expectation. * For example: * <p/> * <pre> * get(..).then(). * root("x.y"). * body("firstName", is(..)). * body("lastName", is(..)). * noRoot() * body("z.something1", is(..)). * body("w.something2", is(..)); * </pre> * <p/> * This is the same as calling <code>rootPath("")</code> but more expressive. * Note that this method is exactly the same as {@link #noRootPath()} but slightly shorter. * * @see #root(String) */ T noRoot(); /** * Reset the root path of the response body so that you don't need to write the entire path for each expectation. * For example: * <p/> * <pre> * get(..).then(). * rootPath("x.y"). * body("firstName", is(..)). * body("lastName", is(..)). * noRootPath() * body("z.something1", is(..)). * body("w.something2", is(..)). * </pre> * <p/> * This is the same as calling <code>rootPath("")</code> but more expressive. * Note that this method is exactly the same as {@link #noRoot()} but slightly more expressive. * * @see #root(String) */ T noRootPath(); /** * Append the given path to the root path of the response body so that you don't need to write the entire path for each expectation. * E.g. instead of writing: * <p/> * <pre> * get(..).then(). * root("x.y"). * body("age", is(..)). * body("gender", is(..)). * body("name.firstName", is(..)). * body("name.lastName", is(..)); * </pre> * <p/> * you can use a append root and do: * <pre> * get(..).then(). * root("x.y"). * body("age", is(..)). * body("gender", is(..)). * appendRoot("name"). * body("firstName", is(..)). * body("lastName", is(..)); * </pre> * * @param pathToAppend The root path to use. */ T appendRoot(String pathToAppend); /** * Append the given path to the root path with arguments supplied of the response body so that you don't need to write the entire path for each expectation. * This is mainly useful when you have parts of the path defined in variables. * E.g. instead of writing: * <p/> * <pre> * String namePath = "name"; * get(..).then(). * root("x.y"). * body("age", is(..)). * body("gender", is(..)). * body(namePath + "first", is(..)). * body(namePath + "last", is(..)). * </pre> * <p/> * you can use a append root and do: * <pre> * String namePath = "name"; * get(..).then(). * root("x.y"). * body("age", is(..)). * body("gender", is(..)). * appendRoot("%s", withArgs(namePath)). * body("first", is(..)). * body("last", is(..)). * </pre> * * @param pathToAppend The root path to use. The path and arguments follows the standard <a href="http://download.oracle.com/javase/1,5.0/docs/api/java/util/Formatter.html#syntax">formatting syntax</a> of Java. */ T appendRoot(String pathToAppend, List<Argument> arguments); /** * Detach the given path from the root path. * E.g. instead of writing: * <p/> * <pre> * when(). * get(..); * then(). * root("x.y"). * body("age", is(..)). * body("gender", is(..)). * root("x"). * body("firstName", is(..)). * body("lastName", is(..)). * </pre> * <p/> * you can use a append root and do: * <pre> * when(). * get(..); * then(). * root("x.y"). * body("age", is(..)). * body("gender", is(..)). * detachRoot("y"). * body("firstName", is(..)). * body("lastName", is(..)). * </pre> * * @param pathToDetach The root path to detach. */ T detachRoot(String pathToDetach); /** * Set the response content type to be <code>contentType</code>. * <p>Note that this will affect the way the response is decoded. * E,g. if you can't use JSON/XML matching (see e.g. {@link #body(String, org.hamcrest.Matcher, Object...)}) if you specify a * content-type of "text/plain". If you don't specify the response content type REST Assured will automatically try to * figure out which content type to use.</p> * * @param contentType The content type of the response. * @return the response specification */ T contentType(ContentType contentType); /** * Set the response content type to be <code>contentType</code>. * <p>Note that this will affect the way the response is decoded. * E,g. if you can't use JSON/XML matching (see e.g. {@link #body(String, org.hamcrest.Matcher, Object...)}) if you specify a * content-type of "text/plain". If you don't specify the response content type REST Assured will automatically try to * figure out which content type to use.</p> * * @param contentType The content type of the response. * @return the response specification */ T contentType(String contentType); /** * Validate the response content type to be <code>contentType</code>. * * @param contentType The expected content type of the response. * @return the response specification */ T contentType(Matcher<? super String> contentType); /** * Validate that the response body conforms to one or more Hamcrest matchers. E.g. * <pre> * // Validate that the response body (content) contains the string "winning-numbers" * get("/lotto").then().assertThat().body(containsString("winning-numbers")); * * // Validate that the response body (content) contains the string "winning-numbers" and "winners" * get("/lotto").then().assertThat().body(containsString("winning-numbers"), containsString("winners")); * </pre> * * @param matcher The hamcrest matcher that must response body must match. * @param additionalMatchers Optionally additional hamcrest matchers that must return <code>true</code>. * @return the response specification */ T body(Matcher<?> matcher, Matcher<?>... additionalMatchers); /** * Compare a path in the response body to something available in the response using arguments. * For example imagine that a resource "/x" returns the following JSON document: * <pre> * { * "userId" : "my-id", * "my.href" : "http://localhost:8080/my-id" * } * </pre> * you can then verify the href using: * <pre> * get("/x").then().body("%s.href", withArgs("my"), new ResponseAwareMatcher<Response>() { * public Matcher<?> matcher(Response response) { * return equalTo("http://localhost:8080/" + response.path("userId")); * } * }); * </pre> * Note that you can also use some of the predefined methods in {@link RestAssuredMatchers}. * * @param path The body path * @param responseAwareMatcher The {@link ResponseAwareMatcher} that creates the Hamcrest matcher. * @return the response specification * @see #body(String, ResponseAwareMatcher) * @see RestAssuredMatchers#endsWithPath(String) * @see RestAssuredMatchers#startsWithPath(String) * @see RestAssuredMatchers#containsPath(String) * @see RestAssuredMatchers#equalToPath(String) */ T body(String path, List<Argument> arguments, ResponseAwareMatcher<R> responseAwareMatcher); /** * Compare a path in the response body to something available in the response, for example another path. * For example imagine that a resource "/x" returns the following JSON document: * <pre> * { * "userId" : "my-id", * "href" : "http://localhost:8080/my-id" * } * </pre> * you can then verify the href using: * <pre> * get("/x").then().body("href", new ResponseAwareMatcher<Response>() { * public Matcher<?> matcher(Response response) { * return equalTo("http://localhost:8080/" + response.path("userId")); * } * }); * </pre> * Note that you can also use some of the predefined methods in {@link RestAssuredMatchers}. * <p> * Note that this method is the same as {@link #content(String, ResponseAwareMatcher)} expect for syntactic differences. * </p> * * @param path The body path * @param responseAwareMatcher The {@link ResponseAwareMatcher} that creates the Hamcrest matcher. * @return the response specification * @see #body(String, java.util.List, ResponseAwareMatcher) * @see RestAssuredMatchers#endsWithPath(String) * @see RestAssuredMatchers#startsWithPath(String) * @see RestAssuredMatchers#containsPath(String) * @see RestAssuredMatchers#equalToPath(String) */ T body(String path, ResponseAwareMatcher<R> responseAwareMatcher); /** * Validate that the JSON or XML response body conforms to one or more Hamcrest matchers.<br> * <h3>JSON example</h3> * <p> * Assume that a GET request to "/lotto" returns a JSON response containing: * <pre> * { "lotto":{ * "lottoId":5, * "winning-numbers":[2,45,34,23,7,5,3], * "winners":[{ * "winnerId":23, * "numbers":[2,45,34,23,3,5] * },{ * "winnerId":54, * "numbers":[52,3,12,11,18,22] * }] * }} * </pre> * <p/> * You can verify that the lottoId is equal to 5 like this: * <pre> * get("/lotto").then().assertThat().body("lotto.lottoId", equalTo(5)); * </pre> * <p/> * You can also verify that e.g. one of the the winning numbers is 45. * <pre> * get("/lotto").then().assertThat().body("lotto.winning-numbers", hasItem(45)); * </pre> * <p/> * Or both at the same time: * <pre> * get("/lotto").then().assertThat().body("lotto.lottoId", equalTo(5)).and().body("lotto.winning-numbers", hasItem(45)); * </pre> * <p/> * or a slightly short version: * <pre> * get("/lotto").then().assertThat().body("lotto.lottoId", equalTo(5), "lotto.winning-numbers", hasItem(45)); * </pre> * </p> * <h3>XML example</h3> * <p> * Assume that a GET request to "/xml" returns a XML response containing: * <pre> * <greeting> * <firstName>John</firstName> * <lastName>Doe</lastName> * </greeting> * </pre> * </p> * <p/> * You can now verify that the firstName is equal to "John" like this: * <pre> * get("/xml").then().assertThat().body("greeting.firstName", equalTo("John")); * </pre> * <p/> * To verify both the first name and last name you can do like this: * <pre> * get("/xml").then().assertThat().body("greeting.firstName", equalTo("John")).and().body("greeting.lastName", equalTo("Doe")); * </pre> * <p/> * Or the slightly shorter version of: * <pre> * get("/xml").then().assertThat().body("greeting.firstName", equalTo("John"), "greeting.lastName", equalTo("Doe")); * </pre> * <h3>Notes</h3> * <p> * Note that if the response body type is not of type <tt>application/xml</tt> or <tt>application/json</tt> you * <i>cannot</i> use this verification. * </p> * <p/> * <p> * The only difference between the <code>content</code> and <code>body</code> methods are of syntactic nature. * </p> * * @param path The body path * @param matcher The hamcrest matcher that must response body must match. * @param additionalKeyMatcherPairs Optionally additional hamcrest matchers that must return <code>true</code>. * @return the response specification */ T body(String path, Matcher<?> matcher, Object... additionalKeyMatcherPairs); /** * Same as {@link #body(String, java.util.List, org.hamcrest.Matcher, Object...)} expect that you can pass arguments to the path. This * is useful in situations where you have e.g. pre-defined variables that constitutes the path: * <pre> * String someSubPath = "else"; * int index = 1; * get("/x").then().assertThat().body("something.%s[%d]", withArgs(someSubPath, index), equalTo("some value")). .. * </pre> * <p/> * or if you have complex root paths and don't wish to duplicate the path for small variations: * <pre> * get("/x").then() * root("filters.filterConfig[%d].filterConfigGroups.find { it.name == 'Gold' }.includes"). * body(withArgs(0), hasItem("first")). * body(withArgs(1), hasItem("second")). * .. * </pre> * <p/> * The path and arguments follows the standard <a href="http://download.oracle.com/javase/1,5.0/docs/api/java/util/Formatter.html#syntax">formatting syntax</a> of Java. * <p> * Note that <code>withArgs</code> can be statically imported from the <code>io.restassured.RestAssured</code> class. * </p> * * @param path The body path * @param matcher The hamcrest matcher that must response body must match. * @param additionalKeyMatcherPairs Optionally additional hamcrest matchers that must return <code>true</code>. * @return the response specification * @see #content(String, org.hamcrest.Matcher, Object...) */ T content(String path, List<Argument> arguments, Matcher matcher, Object... additionalKeyMatcherPairs); /** * Compare a path in the response body to something available in the response using arguments. * For example imagine that a resource "/x" returns the following JSON document: * <pre> * { * "userId" : "my-id", * "my.href" : "http://localhost:8080/my-id" * } * </pre> * you can then verify the href using: * <pre> * get("/x").then().content("%s.href", withArgs("my"), new ResponseAwareMatcher<Response>() { * public Matcher<?> matcher(Response response) { * return equalTo("http://localhost:8080/" + response.path("userId")); * } * }); * </pre> * Note that you can also use some of the predefined methods in {@link RestAssuredMatchers}. * * <p> * Note that this method is the same as {@link #body(String, java.util.List, ResponseAwareMatcher)} expect for syntactic differences. * </p> * * @param path The body path * @param responseAwareMatcher The {@link ResponseAwareMatcher} that creates the Hamcrest matcher. * @return the response specification * @see #content(String, ResponseAwareMatcher) * @see RestAssuredMatchers#endsWithPath(String) * @see RestAssuredMatchers#startsWithPath(String) * @see RestAssuredMatchers#containsPath(String) * @see RestAssuredMatchers#equalToPath(String) */ T content(String path, List<Argument> arguments, ResponseAwareMatcher<R> responseAwareMatcher); /** * Compare a path in the response body to something available in the response, for example another path. * For example imagine that a resource "/x" returns the following JSON document: * <pre> * { * "userId" : "my-id", * "href" : "http://localhost:8080/my-id" * } * </pre> * you can then verify the href using: * <pre> * get("/x").then().content("href", new ResponseAwareMatcher<Response>() { * public Matcher<?> matcher(Response response) { * return equalTo("http://localhost:8080/" + response.path("userId")); * } * }); * </pre> * Note that you can also use some of the predefined methods in {@link RestAssuredMatchers}. * <p> * Note that this method is the same as {@link #body(String, ResponseAwareMatcher)} expect for syntactic differences. * </p> * * @param path The body path * @param responseAwareMatcher The {@link ResponseAwareMatcher} that creates the Hamcrest matcher. * @return the response specification * @see #content(String, java.util.List, ResponseAwareMatcher) * @see RestAssuredMatchers#endsWithPath(String) * @see RestAssuredMatchers#startsWithPath(String) * @see RestAssuredMatchers#containsPath(String) * @see RestAssuredMatchers#equalToPath(String) */ T content(String path, ResponseAwareMatcher<R> responseAwareMatcher); /** * Syntactic sugar, e.g. * <pre> * get("/something").then().assertThat().body(containsString("OK")).and().body(containsString("something else")); * </pre> * <p/> * is that same as: * <pre> * get("/something").then().assertThat().body(containsString("OK")).body(containsString("something else")); * </pre> * * @return the response specification */ T and(); /** * Syntactic sugar, e.g. * <pre> * get("/something").then().using().defaultParser(JSON).assertThat().body(containsString("OK")).and().body(containsString("something else")); * </pre> * <p/> * is that same as: * <pre> * get("/something").then().defaultParser(JSON).body(containsString("OK")).body(containsString("something else")); * </pre> * * @return the response specification */ T using(); /** * Syntactic sugar, e.g. * <pre> * get("/something").then().assertThat().body(containsString("OK")).and().body(containsString("something else")); * </pre> * <p/> * is that same as: * <pre> * get("/something").then().body(containsString("OK")).body(containsString("something else")); * </pre> * * @return the response specification */ T assertThat(); /** * Validate that the response matches an entire specification. * <pre> * ResponseSpecification responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); * get("/something").then() * spec(responseSpec). * body("x.y.z", equalTo("something")); * </pre> * <p/> * This is useful when you want to reuse multiple different expectations in several tests. * <p/> * The specification passed to this method is merged with the current specification. Note that the supplied specification * can overwrite data in the current specification. The following settings are overwritten: * <ul> * <li>Content type</li> * <li>Root path</ * <li>Status code</li> * <li>Status line</li> * </ul> * The following settings are merged: * <ul> * <li>Response body expectations</li> * <li>Cookies</li> * <li>Headers</li> * </ul> * <p/> * This method is the same as {@link #specification(ResponseSpecification)} but the name is a bit shorter. * * @param responseSpecificationToMerge The specification to merge with. * @return the response specification */ T spec(ResponseSpecification responseSpecificationToMerge); /** * Validate that the response matches an entire specification. * <pre> * ResponseSpecification responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); * * get("/something").then(). * specification(responseSpec). * body("x.y.z", equalTo("something")); * </pre> * <p/> * This is useful when you want to reuse multiple different expectations in several tests. * <p/> * The specification passed to this method is merged with the current specification. Note that the supplied specification * can overwrite data in the current specification. The following settings are overwritten: * <ul> * <li>Content type</li> * <li>Root path</ * <li>Status code</li> * <li>Status line</li> * </ul> * The following settings are merged: * <ul> * <li>Response body expectations</li> * <li>Cookies</li> * <li>Headers</li> * </ul> * <p/> * <p/> * This method is the same as {@link #spec(ResponseSpecification)} but the name is a bit longer. * * @param responseSpecificationToMerge The specification to merge with. * @return the response specification */ T specification(ResponseSpecification responseSpecificationToMerge); /** * Register a content-type to be parsed using a predefined parser. E.g. let's say you want parse * content-type <tt>application/custom</tt> with the XML parser to be able to verify the response using the XML dot notations: * <pre> * get("/x").then().assertThat().body("document.child", equalsTo("something") * </pre> * Since <tt>application/custom</tt> is not registered to be processed by the XML parser by default you need to explicitly * tell REST Assured to use this parser before making the request: * <pre> * get("/x").then().parser("application/custom", Parser.XML).assertThat(). ..; * </pre> * <p/> * You can also specify by it for every response by using: * <pre> * RestAssured.registerParser("application/custom", Parser.XML); * </pre> * * @param contentType The content-type to register * @param parser The parser to use when verifying the response. */ T parser(String contentType, Parser parser); /** * Register a default predefined parser that will be used if no other parser (registered or pre-defined) matches the response * content-type. E.g. let's say that for some reason no content-type is defined in the response but the content is nevertheless * JSON encoded. To be able to expect the content in REST Assured you need to set the default parser: * <pre> * get("/x").then().using().defaultParser(Parser.JSON).assertThat(). ..; * </pre> * <p/> * You can also specify it for every response by using: * <pre> * RestAssured.defaultParser(Parser.JSON); * </pre> * * @param parser The parser to use when verifying the response if no other parser is found for the response content-type. */ T defaultParser(Parser parser); /** * Extract values from the response or return the response instance itself. This is useful for example if you want to use values from the * response in sequent requests. For example given that the resource <code>title</code> returns the following JSON * <pre> * { * "title" : "My Title", * "_links": { * "self": { "href": "/title" }, * "next": { "href": "/title?page=2" } * } * } * </pre> * and you want to validate that content type is equal to <code>JSON</code> and the title is equal to <code>My Title</code> * but you also want to extract the link to the "next" title to use that in a subsequent request. This is how: * <pre> * String nextTitleLink = * given(). * param("param_name", "param_value"). * when(). * get("/title"). * then(). * contentType(JSON). * body("title", equalTo("My Title")). * extract(). * path("_links.next.href"); * * get(nextTitleLink). .. * </pre> * * @return An instance of {@link ExtractableResponse}. */ ExtractableResponse<R> extract(); /** * Returns the {@link ValidatableResponseLogSpec} that allows you to log different parts of the {@link Response}. * This is mainly useful for debug purposes when writing your tests. I * * @return the validatable response log specification */ ValidatableResponseLogSpec<T, R> log(); /** * Validate that the response time (in milliseconds) matches the supplied <code>matcher</code>. For example: * <p/> * <pre> * when(). * get("/something"). * then(). * time(lessThan(2000)); * </pre> * <p/> * where <code>lessThan</code> is a Hamcrest matcher * * @return The {@link ValidatableResponse} instance. */ T time(Matcher<Long> matcher); /** * Validate that the response time matches the supplied <code>matcher</code> and time unit. For example: * <p/> * <pre> * when(). * get("/something"). * then(). * time(lessThan(2), TimeUnit.SECONDS); * </pre> * <p/> * where <code>lessThan</code> is a Hamcrest matcher * * @return The {@link ValidatableResponse} instance. */ T time(Matcher<Long> matcher, TimeUnit timeUnit); }