/*
 * Copyright 2002-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 org.springframework.test.web.reactive.server.samples;

import java.net.URI;

import org.junit.Test;
import reactor.core.publisher.Flux;

import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * Samples of tests with serialized JSON content.
 *
 * @author Rossen Stoyanchev
 * @since 5.0
 */
public class JsonContentTests {

	private final WebTestClient client = WebTestClient.bindToController(new PersonController()).build();


	@Test
	public void jsonContent() throws Exception {
		this.client.get().uri("/persons")
				.accept(MediaType.APPLICATION_JSON_UTF8)
				.exchange()
				.expectStatus().isOk()
				.expectBody().json("[{\"name\":\"Jane\"},{\"name\":\"Jason\"},{\"name\":\"John\"}]");
	}

	@Test
	public void jsonPathIsEqualTo() throws Exception {
		this.client.get().uri("/persons")
				.accept(MediaType.APPLICATION_JSON_UTF8)
				.exchange()
				.expectStatus().isOk()
				.expectBody()
				.jsonPath("$[0].name").isEqualTo("Jane")
				.jsonPath("$[1].name").isEqualTo("Jason")
				.jsonPath("$[2].name").isEqualTo("John");
	}

	@Test
	public void postJsonContent() throws Exception {
		this.client.post().uri("/persons")
				.contentType(MediaType.APPLICATION_JSON_UTF8)
				.syncBody("{\"name\":\"John\"}")
				.exchange()
				.expectStatus().isCreated()
				.expectBody().isEmpty();
	}


	@RestController
	static class PersonController {

		@GetMapping("/persons")
		Flux<Person> getPersons() {
			return Flux.just(new Person("Jane"), new Person("Jason"), new Person("John"));
		}

		@PostMapping
		ResponseEntity<String> savePerson(@RequestBody Person person) {
			return ResponseEntity.created(URI.create("/persons/" + person.getName())).build();
		}
	}

}

@@ -758,16 +758,52 @@
 er.Flux;
+%0Aimport reactor.core.publisher.Mono;
 %0A%0Aimport
@@ -1005,32 +1005,93 @@
 ion.GetMapping;%0A
+import org.springframework.web.bind.annotation.PathVariable;%0A
 import org.sprin
@@ -2104,32 +2104,567 @@
 To(%22John%22);%0A%09%7D%0A%0A
+%09@Test%0A%09// See https://stackoverflow.com/questions/49149376/webtestclient-check-that-jsonpath-contains-sub-string%0A%09public void jsonPathContainsSubstringViaRegularExpression() throws Exception %7B%0A%09%09this.client.get().uri(%22/persons/John%22)%0A%09%09%09%09.accept(MediaType.APPLICATION_JSON_UTF8)%0A%09%09%09%09.exchange()%0A%09%09%09%09.expectStatus().isOk()%0A%09%09%09%09.expectBody()%0A%09%09%09%09// The following determines if at least one person is returned with a%0A%09%09%09%09// name containing %22oh%22, and %22John%22 matches that.%0A%09%09%09%09.jsonPath(%22$%5B?(@.name =~ /.*oh.*/)%5D.name%22).hasJsonPath();%0A%09%7D%0A%0A
 %09@Test%0A%09public v
@@ -3013,24 +3013,24 @@
 Persons() %7B%0A
-
 %09%09%09return Fl
@@ -3104,16 +3104,147 @@
 );%0A%09%09%7D%0A%0A
+%09%09@GetMapping(%22/persons/%7Bname%7D%22)%0A%09%09Mono%3CPerson%3E getPerson(@PathVariable String name) %7B%0A%09%09%09return Mono.just(new Person(name));%0A%09%09%7D%0A%0A
 %09%09@PostM

Introduce test for WebTestClient with RegEx-based JsonPath