Skip to content

Commit

Permalink
Merge pull request #1567 from lnash94/5720
Browse files Browse the repository at this point in the history
[master] Provide nil return support for the client generation when the response has no content type instead of giving `http:Response`
  • Loading branch information
lnash94 authored Nov 14, 2023
2 parents 6f46ee5 + 1f2b689 commit 180c373
Show file tree
Hide file tree
Showing 31 changed files with 328 additions and 191 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,25 +89,20 @@ public Object[][] dataProviderForFunctionBody() {
"http:Responseresponse=check self.clientEp-> head(resourcePath, httpHeaders);returnresponse;}"},
{"diagnostic_files/operation_delete.yaml", "/pets/{petId}", "{string resourcePath = " +
"string `/pets/${getEncodedUri(petId)}`;" +
"http:Response response = check self.clientEp-> delete(resourcePath);" +
"return response;}"},
"return self.clientEp-> delete(resourcePath);}"},
{"diagnostic_files/json_payload.yaml", "/pets", "{string resourcePath = string `/pets`;" +
"http:Request request = new; request.setPayload(payload, \"application/json\"); " +
"http:Response response = check self.clientEp->" +
"post(resourcePath, request); " +
"return response;}"},
"return self.clientEp->post(resourcePath, request);}"},
{"diagnostic_files/xml_payload.yaml", "/pets", "{string resourcePath = string `/pets`; " +
"http:Request request = new;" +
"request.setPayload(payload, \"application/xml\"); " +
"http:Response response = check self.clientEp->post(resourcePath, request);" +
"return response;}"},
"return self.clientEp->post(resourcePath, request);}"},
{"diagnostic_files/xml_payload_with_ref.yaml", "/pets", "{string resourcePath = string `/pets`;" +
"http:Request request = new;" +
"json jsonBody = payload.toJson();" +
"xml? xmlBody = check xmldata:fromJson(jsonBody);" +
"request.setPayload(xmlBody, \"application/xml\");" +
"http:Response response = check self.clientEp->post(resourcePath, request);" +
"return response;}"},
"return self.clientEp->post(resourcePath, request);}"},
{"client/swagger/response_type_order.yaml", "/pet/{petId}",
"{string resourcePath = string `/pet/${getEncodedUri(petId)}`;" +
"Pet response = check self.clientEp->get(resourcePath);" +
Expand All @@ -120,13 +115,11 @@ public Object[][] dataProviderForFunctionBody() {
"return response;}"},
{"client/swagger/pdf_payload.yaml", "/pets", "{string resourcePath = string `/pets`;" +
"// TODO: Update the request as needed;\n" +
"http:Response response = check self.clientEp->post(resourcePath, request);" +
"return response;}"},
" return self.clientEp->post(resourcePath, request);}"},
{"client/swagger/image_payload.yaml", "/pets", "{string resourcePath = string `/pets`;" +
"http:Request request = new;" +
"request.setPayload(payload, \"image/png\");" +
"http:Response response = check self.clientEp->post(resourcePath, request);" +
"return response;}"},
" return self.clientEp->post(resourcePath, request);}"},
{"client/swagger/multipart_formdata_custom.yaml", "/pets", "{string resourcePath = string `/pets`;\n" +
"http:Request request = new;\n" +
"map<Encoding> encodingMap = {\"profileImage\": {contentType: \"image/png\", headers: " +
Expand All @@ -135,8 +128,7 @@ public Object[][] dataProviderForFunctionBody() {
"{contentType:\"text/plain\"}};\n" +
"mime:Entity[] bodyParts = check createBodyParts(payload, encodingMap);\n" +
"request.setBodyParts(bodyParts);\n" +
"http:Response response = check self.clientEp->post(resourcePath, request);\n" +
"return response;}"},
" return self.clientEp->post(resourcePath, request);\n}"},
{"client/swagger/empty_object_responnse.yaml", "/pets", "{string resourcePath = string `/pets`;\n" +
" // TODO: Update the request as needed;\n" +
" json response = check self.clientEp->post(resourcePath, request);\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public void testFunctionSignatureNodeForXMLPayload() throws IOException, Balleri
Assert.assertEquals(param01.typeName().toString(), "xml");

ReturnTypeDescriptorNode returnTypeNode = signature.returnTypeDesc().orElseThrow();
Assert.assertEquals(returnTypeNode.type().toString(), "http:Response|error");
Assert.assertEquals(returnTypeNode.type().toString(), "error?");
}

@Test(description = "Test for generate function signature for json request body")
Expand All @@ -120,7 +120,7 @@ public void testFunctionSignatureNodeForJSONPayload() throws IOException, Baller
Assert.assertEquals(param01.typeName().toString(), "json");

ReturnTypeDescriptorNode returnTypeNode = signature.returnTypeDesc().orElseThrow();
Assert.assertEquals(returnTypeNode.type().toString(), "http:Response|error");
Assert.assertEquals(returnTypeNode.type().toString(), "error?");
}

@Test(description = "Test for generate function signature for multipart custom header")
Expand All @@ -147,7 +147,7 @@ public void testFunctionSignatureNodeForMultipartCustomHeader() throws IOExcepti
Assert.assertEquals(param03.typeName().toString(), "string?");

ReturnTypeDescriptorNode returnTypeNode = signature.returnTypeDesc().orElseThrow();
Assert.assertEquals(returnTypeNode.type().toString(), "http:Response|error");
Assert.assertEquals(returnTypeNode.type().toString(), "error?");
}

@Test(description = "Test for generate function signature with nested array return type")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@

package io.ballerina.openapi.generators.client;

import io.ballerina.compiler.syntax.tree.SyntaxTree;
import io.ballerina.openapi.core.exception.BallerinaOpenApiException;
import io.ballerina.openapi.core.generators.client.BallerinaClientGenerator;
import io.ballerina.openapi.core.generators.client.FunctionReturnTypeGenerator;
import io.ballerina.openapi.core.generators.client.model.OASClientConfig;
import io.ballerina.openapi.core.generators.schema.BallerinaTypesGenerator;
import io.ballerina.openapi.core.model.Filter;
import io.swagger.v3.oas.models.OpenAPI;
import org.testng.Assert;
import org.testng.annotations.Test;
Expand All @@ -29,7 +33,9 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import static io.ballerina.openapi.generators.common.TestUtils.compareGeneratedSyntaxTreeWithExpectedSyntaxTree;
import static io.ballerina.openapi.generators.common.TestUtils.getOpenAPI;

/**
Expand All @@ -54,6 +60,9 @@ public void getReturnTypeTests() throws IOException, BallerinaOpenApiException {
true), "xml[]|error");
Assert.assertEquals(functionReturnType.getReturnType(array.getPaths().get("/xmlarrayproducts").getGet(),
false), "XMLArr|error");
String returnType = functionReturnType.getReturnType(array.getPaths().get("/products/nocontent").getGet(),
true);
Assert.assertEquals(returnType, "error?");
}

@Test(description = "Tests for the object response without property")
Expand Down Expand Up @@ -129,4 +138,21 @@ public void getReturnTypeForAdditionalPropertySchema() throws IOException, Balle
true);
Assert.assertEquals(returnType, "json|error");
}

@Test(description = "Tests for the response without content type")
public void getReturnTypeForNoContentType() throws IOException, BallerinaOpenApiException {
OpenAPI openAPI = getOpenAPI(RES_DIR.resolve("swagger/return_type" +
"/no_content_type.yaml"));
Path expectedPath = RES_DIR.resolve("ballerina/return/no_content_type.bal");

List<String> list1 = new ArrayList<>();
Filter filter = new Filter(list1, list1);
OASClientConfig.Builder clientMetaDataBuilder = new OASClientConfig.Builder();
OASClientConfig oasClientConfig = clientMetaDataBuilder
.withFilters(filter)
.withOpenAPI(openAPI).build();
BallerinaClientGenerator ballerinaClientGenerator = new BallerinaClientGenerator(oasClientConfig);
SyntaxTree syntaxTree = ballerinaClientGenerator.generateSyntaxTree();
compareGeneratedSyntaxTreeWithExpectedSyntaxTree(expectedPath, syntaxTree);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,11 @@ public isolated client class Client {
# Creates a new user.
#
# + return - OK
remote isolated function createUser(User payload) returns http:Response|error {
remote isolated function createUser(User payload) returns error? {
string resourcePath = string `/requestBody`;
http:Request request = new;
json jsonBody = payload.toJson();
request.setPayload(jsonBody, "application/json");
http:Response response = check self.clientEp->post(resourcePath, request);
return response;
return self.clientEp->post(resourcePath, request);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,9 @@ public isolated client class Client {
# Create a pet
#
# + return - Null response
remote isolated function createPet(http:Request request) returns http:Response|error {
remote isolated function createPet(http:Request request) returns error? {
string resourcePath = string `/pets`;
// TODO: Update the request as needed;
http:Response response = check self.clientEp->post(resourcePath, request);
return response;
return self.clientEp->post(resourcePath, request);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,11 @@ public isolated client class Client {
# Create a pet
#
# + return - Null response
remote isolated function createPet(byte[] payload) returns http:Response|error {
remote isolated function createPet(byte[] payload) returns error? {
string resourcePath = string `/pets`;
http:Request request = new;
request.setPayload(payload, "application/octet-stream");
http:Response response = check self.clientEp->post(resourcePath, request);
return response;
return self.clientEp->post(resourcePath, request);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,12 @@ public isolated client class Client {
# Create a pet
#
# + return - Null response
remote isolated function createPet(byte[] payload) returns http:Response|error {
remote isolated function createPet(byte[] payload) returns error? {
string resourcePath = string `/pets`;
http:Request request = new;
string encodedRequestBody = payload.toBase64();
request.setPayload(encodedRequestBody, "application/octet-stream");
http:Response response = check self.clientEp->post(resourcePath, request);
return response;
return self.clientEp->post(resourcePath, request);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -39,43 +39,39 @@ public isolated client class Client {
# + order_id - Order ID
# + risk_id - Order Risk ID
# + return - Status OK
remote isolated function delete_order_risk(string order_id, string risk_id) returns http:Response|error {
remote isolated function delete_order_risk(string order_id, string risk_id) returns error? {
string resourcePath = string `/admin/api/2021-10/orders/${getEncodedUri(order_id)}/risks/${getEncodedUri(risk_id)}.json`;
http:Response response = check self.clientEp-> delete(resourcePath);
return response;
return self.clientEp-> delete(resourcePath);
}
# Delete with request body.
#
# + return - Status OK
remote isolated function order_risk(json payload) returns http:Response|error {
remote isolated function order_risk(json payload) returns error? {
string resourcePath = string `/request-body`;
http:Request request = new;
request.setPayload(payload, "application/json");
http:Response response = check self.clientEp->delete(resourcePath, request);
return response;
return self.clientEp->delete(resourcePath, request);
}
# Delete with header.
#
# + xRequestId - Tests header 01
# + return - Status OK
remote isolated function deleteHeader(string xRequestId) returns http:Response|error {
remote isolated function deleteHeader(string xRequestId) returns error? {
string resourcePath = string `/header`;
map<any> headerValues = {"X-Request-ID": xRequestId};
map<string|string[]> httpHeaders = getMapForHeaders(headerValues);
http:Response response = check self.clientEp->delete(resourcePath, headers = httpHeaders);
return response;
return self.clientEp->delete(resourcePath, headers = httpHeaders);
}
# Delete with header and request body.
#
# + xRequestId - Tests header 01
# + return - Status OK
remote isolated function deleteHeaderRequestBody(string xRequestId, json payload) returns http:Response|error {
remote isolated function deleteHeaderRequestBody(string xRequestId, json payload) returns error? {
string resourcePath = string `/header-with-request-body`;
map<any> headerValues = {"X-Request-ID": xRequestId};
map<string|string[]> httpHeaders = getMapForHeaders(headerValues);
http:Request request = new;
request.setPayload(payload, "application/json");
http:Response response = check self.clientEp->delete(resourcePath, request, httpHeaders);
return response;
return self.clientEp->delete(resourcePath, request, httpHeaders);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,9 @@ public isolated client class Client {
#
# + request - Pet
# + return - Null response
remote isolated function createPet(http:Request request) returns http:Response|error {
remote isolated function createPet(http:Request request) returns error? {
string resourcePath = string `/pets`;
// TODO: Update the request as needed;
http:Response response = check self.clientEp->post(resourcePath, request);
return response;
return self.clientEp->post(resourcePath, request);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,23 @@ public isolated client class Client {
#
# + payload - Pet
# + return - Null response
remote isolated function createPet(Pets_body payload) returns http:Response|error {
remote isolated function createPet(Pets_body payload) returns error? {
string resourcePath = string `/pets`;
http:Request request = new;
mime:Entity[] bodyParts = check createBodyParts(payload);
request.setBodyParts(bodyParts);
http:Response response = check self.clientEp->post(resourcePath, request);
return response;
return self.clientEp->post(resourcePath, request);
}

# Create an user
#
# + payload - User
# + return - Null response
remote isolated function createUser(User_body payload) returns http:Response|error {
remote isolated function createUser(User_body payload) returns error? {
string resourcePath = string `/user`;
http:Request request = new;
mime:Entity[] bodyParts = check createBodyParts(payload);
request.setBodyParts(bodyParts);
http:Response response = check self.clientEp->post(resourcePath, request);
return response;
return self.clientEp->post(resourcePath, request);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,9 @@ public isolated client class Client {
#
# + request - Pet
# + return - Null response
remote isolated function createPet(http:Request request) returns http:Response|error {
remote isolated function createPet(http:Request request) returns error? {
string resourcePath = string `/pets`;
// TODO: Update the request as needed;
http:Response response = check self.clientEp->post(resourcePath, request);
return response;
return self.clientEp->post(resourcePath, request);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,20 @@ public isolated client class Client {
# Creates a new user.
#
# + return - OK
resource isolated function post user(byte[] payload) returns http:Response|error {
resource isolated function post user(byte[] payload) returns error? {
string resourcePath = string `/user`;
http:Request request = new;
request.setPayload(payload, "application/octet-stream");
http:Response response = check self.clientEp->post(resourcePath, request);
return response;
return self.clientEp->post(resourcePath, request);
}
# Creates a new payment.
#
# + payload - Details of the pet to be purchased
# + return - OK
resource isolated function post payment(byte[] payload) returns http:Response|error {
resource isolated function post payment(byte[] payload) returns error? {
string resourcePath = string `/payment`;
http:Request request = new;
request.setPayload(payload, "application/octet-stream");
http:Response response = check self.clientEp->post(resourcePath, request);
return response;
return self.clientEp->post(resourcePath, request);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,36 +39,33 @@ public isolated client class Client {
# Request Body has allOf with specific properties.
#
# + return - OK
remote isolated function updateXMLUser(Path01_body payload) returns http:Response|error {
remote isolated function updateXMLUser(Path01_body payload) returns error? {
string resourcePath = string `/path01`;
http:Request request = new;
json jsonBody = payload.toJson();
xml? xmlBody = check xmldata:fromJson(jsonBody);
request.setPayload(xmlBody, "application/xml");
http:Response response = check self.clientEp->put(resourcePath, request);
return response;
return self.clientEp->put(resourcePath, request);
}
# Request Body has nested allOf.
#
# + return - OK
remote isolated function postXMLUser(Path01_body_1 payload) returns http:Response|error {
remote isolated function postXMLUser(Path01_body_1 payload) returns error? {
string resourcePath = string `/path01`;
http:Request request = new;
json jsonBody = payload.toJson();
request.setPayload(jsonBody, "application/json");
http:Response response = check self.clientEp->post(resourcePath, request);
return response;
return self.clientEp->post(resourcePath, request);
}
# Request Body has Array type AllOf.
#
# + return - OK
remote isolated function postXMLUserInLineArray(CompoundArrayItemPostXMLUserInLineArrayRequest payload) returns http:Response|error {
remote isolated function postXMLUserInLineArray(CompoundArrayItemPostXMLUserInLineArrayRequest payload) returns error? {
string resourcePath = string `/path02`;
http:Request request = new;
json jsonBody = payload.toJson();
xml? xmlBody = check xmldata:fromJson(jsonBody);
request.setPayload(xmlBody, "application/xml");
http:Response response = check self.clientEp->post(resourcePath, request);
return response;
return self.clientEp->post(resourcePath, request);
}
}
Loading

0 comments on commit 180c373

Please sign in to comment.