-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PP-13030: Use CreateServiceRequest pojo instead of JsonNode #2653
Changes from all commits
c8e53c2
9ac402e
e8469ed
a2a8bc8
23e1f1d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -343,6 +343,8 @@ paths: | |
schema: | ||
$ref: '#/components/schemas/Service' | ||
description: Created | ||
"400": | ||
description: Service name keys must be one of 'en' (English) or 'cy' (Welsh) | ||
"409": | ||
description: Gateway account IDs provided has already been assigned to another | ||
service | ||
|
@@ -1184,6 +1186,17 @@ components: | |
example: [email protected] | ||
required: | ||
CreateServiceRequest: | ||
type: object | ||
properties: | ||
gateway_account_ids: | ||
type: array | ||
items: | ||
type: string | ||
service_name: | ||
type: object | ||
additionalProperties: | ||
type: string | ||
CreateUserRequest: | ||
type: object | ||
properties: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package uk.gov.pay.adminusers.model; | ||
|
||
import com.fasterxml.jackson.databind.PropertyNamingStrategies; | ||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; | ||
import com.fasterxml.jackson.databind.annotation.JsonNaming; | ||
import uk.gov.service.payments.commons.model.SupportedLanguage; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) | ||
public record CreateServiceRequest( | ||
List<String> gatewayAccountIds, | ||
@JsonDeserialize(using = ServiceNamesDeserializer.class) Map<SupportedLanguage, String> serviceName) { | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package uk.gov.pay.adminusers.model; | ||
|
||
import com.fasterxml.jackson.core.JsonParser; | ||
import com.fasterxml.jackson.core.type.TypeReference; | ||
import com.fasterxml.jackson.databind.DeserializationContext; | ||
import com.fasterxml.jackson.databind.JsonDeserializer; | ||
import uk.gov.service.payments.commons.model.SupportedLanguage; | ||
|
||
import java.io.IOException; | ||
import java.util.Map; | ||
|
||
import static java.util.stream.Collectors.toUnmodifiableMap; | ||
|
||
public class ServiceNamesDeserializer extends JsonDeserializer<Map<SupportedLanguage, String>> { | ||
@Override | ||
public Map<SupportedLanguage, String> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { | ||
return jsonParser.getCodec().readValue(jsonParser, new TypeReference<Map<String, String>>() {}) | ||
.entrySet().stream() | ||
.collect(toUnmodifiableMap(entry -> SupportedLanguage.fromIso639AlphaTwoCode(entry.getKey()), Map.Entry::getValue)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,117 @@ | ||
package uk.gov.pay.adminusers.resources; | ||
|
||
import com.fasterxml.jackson.databind.JsonNode; | ||
import io.restassured.response.ValidatableResponse; | ||
import org.junit.jupiter.api.DisplayNameGeneration; | ||
import org.junit.jupiter.api.DisplayNameGenerator; | ||
import org.junit.jupiter.api.Test; | ||
import uk.gov.service.payments.commons.model.SupportedLanguage; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import static io.restassured.http.ContentType.JSON; | ||
import static org.hamcrest.Matchers.emptyIterable; | ||
import static org.hamcrest.Matchers.hasEntry; | ||
import static org.hamcrest.Matchers.is; | ||
import static org.hamcrest.Matchers.not; | ||
import static org.hamcrest.Matchers.nullValue; | ||
import static uk.gov.service.payments.commons.model.SupportedLanguage.ENGLISH; | ||
import static uk.gov.service.payments.commons.model.SupportedLanguage.WELSH; | ||
|
||
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) | ||
class ServiceResourceCreateIT extends IntegrationTest { | ||
|
||
@Test | ||
void shouldCreateService() { | ||
JsonNode payload = mapper | ||
.valueToTree(Map.of( | ||
"service_name", Map.of(SupportedLanguage.ENGLISH.toString(), "Service name"), | ||
"gateway_account_ids", List.of("1") | ||
)); | ||
|
||
givenSetup() | ||
void create_service_with_all_parameters_successfully() { | ||
var validatableResponse = givenSetup() | ||
.when() | ||
.contentType(JSON) | ||
.body(payload) | ||
.body(Map.of("service_name", Map.of(ENGLISH.toString(), "Service name"), | ||
"gateway_account_ids", List.of("1"))) | ||
.post("v1/api/services") | ||
.then() | ||
.statusCode(201) | ||
.body("created_date", is(not(nullValue()))) | ||
.body("gateway_account_ids", is(List.of("1"))) | ||
.body("service_name", hasEntry("en", "Service name")); | ||
|
||
assertStandardFields(validatableResponse); | ||
} | ||
|
||
@Test | ||
void can_create_default_service_with_empty_request_body() { | ||
var validatableResponse = givenSetup() | ||
.when() | ||
.contentType(JSON) | ||
.post("v1/api/services") | ||
.then() | ||
.statusCode(201) | ||
.body("created_date", is(not(nullValue()))) | ||
.body("gateway_account_ids", is(emptyIterable())) | ||
.body("service_name", hasEntry("en", "System Generated")) | ||
.body("name", is("System Generated")); | ||
|
||
assertStandardFields(validatableResponse); | ||
} | ||
|
||
@Test | ||
void can_create_default_service_with_gateway_account_ids_only() { | ||
var validatableResponse = givenSetup() | ||
.when() | ||
.contentType(JSON) | ||
.body(Map.of("gateway_account_ids", List.of("1", "2"))) | ||
.post("v1/api/services") | ||
.then() | ||
.statusCode(201) | ||
.body("created_date", is(not(nullValue()))) | ||
.body("gateway_account_ids", is(List.of("1", "2"))) | ||
.body("service_name", hasEntry("en", "System Generated")) | ||
.body("name", is("System Generated")); | ||
|
||
assertStandardFields(validatableResponse); | ||
} | ||
|
||
@Test | ||
void can_create_default_service_with_service_name_only() { | ||
var validatableResponse = givenSetup() | ||
.when() | ||
.contentType(JSON) | ||
.body(Map.of("service_name", Map.of(ENGLISH.toString(), "Service name", WELSH.toString(), "Welsh name"))) | ||
.post("v1/api/services") | ||
.then() | ||
.statusCode(201) | ||
.body("created_date", is(not(nullValue()))) | ||
.body("gateway_account_ids", is(emptyIterable())) | ||
.body("service_name", hasEntry("en", "Service name")) | ||
.body("service_name", hasEntry("cy", "Welsh name")) | ||
.body("name", is("Service name")); | ||
|
||
assertStandardFields(validatableResponse); | ||
} | ||
|
||
private void assertStandardFields(ValidatableResponse validatableResponse) { | ||
validatableResponse | ||
.body("current_psp_test_account_stage", is("NOT_STARTED")) | ||
.body("current_go_live_stage", is("NOT_STARTED")) | ||
.body("default_billing_address_country", is("GB")) | ||
.body("agent_initiated_moto_enabled", is(false)) | ||
.body("takes_payments_over_phone", is(false)) | ||
.body("experimental_features_enabled", is(false)) | ||
.body("internal", is(false)) | ||
.body("archived", is(false)) | ||
.body("redirect_to_service_immediately_on_terminal_state", is(false)) | ||
.body("collect_billing_address", is(true)); | ||
} | ||
|
||
@Test | ||
void return_bad_request_when_invalid_supported_language_provided() { | ||
givenSetup() | ||
.when() | ||
.contentType(JSON) | ||
.body(Map.of("service_name", Map.of("fr", "Service name"))) | ||
.post("v1/api/services") | ||
.then() | ||
.statusCode(400) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Returning a 422 might be more correct here, but getting Jersey to do this from within a custom deserialiser is very hard to do. We return a 400 in other places so I think this is acceptable. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree this is fine for an internal API. |
||
.body("message", is("Unable to process JSON")) | ||
.body("details", is("fr is not a supported ISO 639-1 code")); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presumably the entire
createServiceRequest
is not going to be null but the list of gateway account IDs or map of languages to service names might be, so perhaps this would be better:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
createServiceRequest
is null actually.... otherwise your suggestion would be the better option!There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would be easier:
But am not very fussed here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⬆️ Actually my suggestion wouldn't work 🙈
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this would work:
It would get rid of the need to have the
nullableCreateServiceRequest
variable at the expense of an extraOptional.ofNullable(…)
call (the cost of which is probably absolutely trivial).This could be slightly rearranged to surface the actual data and types involved a bit more: