[R][client] Make enum parameters with required: false optional to request arguments (#19654)

* ODM-11697: Adding null check in R-api

* bin/generate-samples.sh executed

---------

Co-authored-by: Kunitsyn Oleg <114428801+genestack-okunitsyn@users.noreply.github.com>
This commit is contained in:
Viacheslav Pivovarov 2024-10-05 11:12:30 +04:00 committed by GitHub
parent 77eb192414
commit e5dee54797
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 77 additions and 9 deletions

View File

@ -324,7 +324,7 @@
{{#items}}
{{#isEnum}}
# validate enum values
if (!(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
if (!is.null(query_item) && !(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
{{#useDefaultExceptionHandling}}
stop("Invalid value for {{{paramName}}} when calling {{classname}}${{operationId}}. Must be {{_enum}}.")
{{/useDefaultExceptionHandling}}
@ -346,7 +346,7 @@
{{#isEnum}}
# validate enum values
for (query_item in `{{{paramName}}}`) {
if (!(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
if (!is.null(query_item) && !(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
{{#useDefaultExceptionHandling}}
stop("Invalid value for {{{paramName}}} when calling {{classname}}${{operationId}}. Must be {{_enum}}.")
{{/useDefaultExceptionHandling}}
@ -370,7 +370,7 @@
{{#items}}
{{#isEnum}}
# validate enum values
if (!(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
if (!is.null(query_item) && !(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
{{#useDefaultExceptionHandling}}
stop("Invalid value for {{{paramName}}} when calling {{classname}}${{operationId}}. Must be {{_enum}}.")
{{/useDefaultExceptionHandling}}
@ -392,7 +392,7 @@
{{#isEnum}}
# validate enum values
for (query_item in `{{{paramName}}}`) {
if (!(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
if (!is.null(query_item) && !(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
{{#useDefaultExceptionHandling}}
stop("Invalid value for {{{paramName}}} when calling {{classname}}${{operationId}}. Must be {{_enum}}.")
{{/useDefaultExceptionHandling}}
@ -412,7 +412,7 @@
{{/isArray}}
{{^isArray}}
{{#isEnum}}
if (!(`{{paramName}}` %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
if (!is.null(`{{paramName}}`) && !(`{{paramName}}` %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
{{#useDefaultExceptionHandling}}
stop("Invalid value for {{{paramName}}} when calling {{classname}}${{operationId}}. Must be {{_enum}}.")
{{/useDefaultExceptionHandling}}

View File

@ -17,11 +17,21 @@
package org.openapitools.codegen.r;
import io.swagger.v3.oas.models.OpenAPI;
import org.openapitools.codegen.ClientOptInput;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.DefaultGenerator;
import org.openapitools.codegen.TestUtils;
import org.openapitools.codegen.languages.RClientCodegen;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.regex.Pattern;
public class RClientCodegenTest {
@Test
@ -53,4 +63,35 @@ public class RClientCodegenTest {
Assert.assertEquals(codegen.isHideGenerationTimestamp(), false);
}
@Test
public void testNullCheckOnEnumValues() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
final DefaultGenerator defaultGenerator = new DefaultGenerator();
RClientCodegen rClientCodegen = new RClientCodegen();
rClientCodegen.setOutputDir(output.getAbsolutePath());
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/bugs/issue_18016.yaml");
final ClientOptInput clientOptInput = new ClientOptInput();
clientOptInput.openAPI(openAPI);
clientOptInput.config(rClientCodegen);
defaultGenerator.opts(clientOptInput);
var petsApi = defaultGenerator.generate().stream()
.filter(file -> "pets_api.R".equals(file.getName())).findFirst();
if (petsApi.isEmpty()) {
Assert.fail("`pets_api.R` have not been generated");
}
var isIfCondition = Pattern.compile("^\\s*(?!<#)\\s*if.*\\s%in%\\s.*").asPredicate();
var containsNullCheck = Pattern.compile("![(\\s]*is\\.null").asPredicate();
var hit = false;
for (var line: Files.readAllLines(Paths.get(petsApi.get().getAbsolutePath()))) {
if (isIfCondition.test(line)) {
hit = true;
Assert.assertTrue(containsNullCheck.test(line), "Null check is missing in line: " + line);
}
}
Assert.assertTrue(hit, "No if statement for enum found");
}
}

View File

@ -0,0 +1,27 @@
openapi: "3.0.0"
info:
version: 1.0.0
description: Specification to generate null check for enums in R client
title: RClientNullCheck
paths:
/exists:
get:
tags:
- pets
parameters:
- name: type
in: query
description: Type of pet
required: false
schema:
enum:
- cat
- dog
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: boolean

View File

@ -223,7 +223,7 @@ QueryApi <- R6::R6Class(
if (!(`enum_nonref_string_query` %in% c("success", "failure", "unclassified"))) {
if (!is.null(`enum_nonref_string_query`) && !(`enum_nonref_string_query` %in% c("success", "failure", "unclassified"))) {
stop("Invalid value for enum_nonref_string_query when calling QueryApi$TestEnumRefString. Must be [success, failure, unclassified].")
}
query_params[["enum_nonref_string_query"]] <- `enum_nonref_string_query`

View File

@ -664,7 +664,7 @@ PetApi <- R6::R6Class(
# explore
for (query_item in `status`) {
# validate enum values
if (!(query_item %in% c("available", "pending", "sold"))) {
if (!is.null(query_item) && !(query_item %in% c("available", "pending", "sold"))) {
rlang::abort(message = "Invalid value for `status` when calling PetApi$find_pets_by_status. Must be [available, pending, sold].",
.subclass = "ApiException",
ApiException = ApiException$new(status = 0,

View File

@ -664,7 +664,7 @@ PetApi <- R6::R6Class(
# explore
for (query_item in `status`) {
# validate enum values
if (!(query_item %in% c("available", "pending", "sold"))) {
if (!is.null(query_item) && !(query_item %in% c("available", "pending", "sold"))) {
rlang::abort(message = "Invalid value for `status` when calling PetApi$find_pets_by_status. Must be [available, pending, sold].",
.subclass = "ApiException",
ApiException = ApiException$new(status = 0,

View File

@ -664,7 +664,7 @@ PetApi <- R6::R6Class(
# explore
for (query_item in `status`) {
# validate enum values
if (!(query_item %in% c("available", "pending", "sold"))) {
if (!is.null(query_item) && !(query_item %in% c("available", "pending", "sold"))) {
rlang::abort(message = "Invalid value for `status` when calling PetApi$FindPetsByStatus. Must be [available, pending, sold].",
.subclass = "ApiException",
ApiException = ApiException$new(status = 0,