/*
 * (c) Copyright 2017 Palantir Technologies Inc. All rights reserved.
 *
 * 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 com.palantir.conjure.java.server.jersey;

import static org.assertj.core.api.Assertions.assertThat;

import io.dropwizard.Application;
import io.dropwizard.Configuration;
import io.dropwizard.setup.Environment;
import io.dropwizard.testing.junit.DropwizardAppRule;
import javax.annotation.Nullable;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.client.JerseyClientBuilder;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;

public final class StringFormatTest {

    @ClassRule
    public static final DropwizardAppRule<Configuration> APP = new DropwizardAppRule<>(TestServer.class,
            "src/test/resources/test-server.yml");

    private WebTarget target;

    @Before
    public void before() {
        String endpointUri = "http://localhost:" + APP.getLocalPort();
        JerseyClientBuilder builder = new JerseyClientBuilder();
        Client client = builder.build();
        target = client.target(endpointUri);
    }

    @Test
    public void testTextPlainMediaTypeReturnsPlainStrings() {
        Response response = target.path("textString").request().get();
        assertThat(response.readEntity(String.class)).isEqualTo("");
        response = target.path("textString").queryParam("value", "val").request().get();
        assertThat(response.readEntity(String.class)).isEqualTo("val");
    }

    @Test
    public void testJsonMediaTypeReturnsPlainStrings() {
        // This behaviour is somewhat unexpected since a valid JSON response object would be "\"val\"" rather than "val"
        Response response = target.path("jsonString").request().get();
        assertThat(response.readEntity(String.class)).isEqualTo("");
        response = target.path("jsonString").queryParam("value", "val").request().get();
        assertThat(response.readEntity(String.class)).isEqualTo("val");
    }

    public static class TestServer extends Application<Configuration> {
        @Override
        public final void run(Configuration _config, final Environment env) throws Exception {
            env.jersey().register(ConjureJerseyFeature.INSTANCE);
            env.jersey().register(new TestResource());
        }
    }

    public static final class TestResource implements TestService {
        @Override
        public String getJsonString(@Nullable String value) {
            return value;
        }

        @Override
        public String getTextString(@Nullable String value) {
            return value;
        }
    }

    @Path("/")
    @Consumes(MediaType.APPLICATION_JSON)
    public interface TestService {

        @GET
        @Path("/jsonString")
        @Produces(MediaType.APPLICATION_JSON)
        String getJsonString(@QueryParam("value") @Nullable String value);

        @GET
        @Path("/textString")
        @Produces(MediaType.TEXT_PLAIN)
        String getTextString(@QueryParam("value") @Nullable String value);
    }
}

@@ -989,16 +989,41 @@
 rs.GET;%0A
+import javax.ws.rs.POST;%0A
 import j
@@ -1039,16 +1039,16 @@
 s.Path;%0A
-
 import j
@@ -1129,24 +1129,58 @@
 ent.Client;%0A
+import javax.ws.rs.client.Entity;%0A
 import javax
@@ -2784,32 +2784,589 @@
 (%22val%22);%0A    %7D%0A%0A
+    @Test%0A    public void testJsonStringBodyDeserializedAsPlainString() %7B%0A        // This behaviour is somewhat unexpected since a valid JSON string is deserialized as a raw string, even%0A        // though the endpoint consumes application/json%0A        Response response = target.path(%22bodyString%22).request().post(null);%0A        assertThat(response.readEntity(String.class)).isEqualTo(%22%22);%0A        response = target.path(%22bodyString%22).request().post(Entity.json(%22%5C%22val%5C%22%22));%0A        assertThat(response.readEntity(String.class)).isEqualTo(%22%5C%22val%5C%22%22);%0A    %7D%0A%0A
     public stati
@@ -3964,32 +3964,140 @@
 value;%0A        %7D
+%0A%0A        @Override%0A        public String postJsonString(String value) %7B%0A            return value;%0A        %7D
 %0A    %7D%0A%0A    @Pat
@@ -4427,16 +4427,16 @@
 _PLAIN)%0A
-
         
@@ -4501,16 +4501,155 @@
  value);
+%0A%0A        @POST%0A        @Path(%22/bodyString%22)%0A        @Produces(MediaType.TEXT_PLAIN)%0A        String postJsonString(@Nullable String value);
 %0A    %7D%0A%7D

Add test demonstrating the deserialization behavior of JSON string body (#1395)