Skip to content

Commit

Permalink
[elm][haskell-servant] Fix issue 3256 (OpenAPITools#3262)
Browse files Browse the repository at this point in the history
* [elm] fix empty operation exception (OpenAPITools#3256)

* [haskell-servant] fix empty operation type (OpenAPITools#3256)

* [elm][haskell-servant] update samples
  • Loading branch information
Elewyth authored and wing328 committed Jul 3, 2019
1 parent 35262aa commit 95ba952
Show file tree
Hide file tree
Showing 48 changed files with 1,799 additions and 178 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,9 @@ public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> o
op.path = ("\"" + path + "\"").replaceAll(" \\+\\+ \"\"", "");
} else {
final List<String> paths = Arrays.asList(op.path.substring(1).split("/"));
String path = paths.stream().map(str -> str.charAt(0) == '{' ? str : "\"" + str + "\"").collect(Collectors.joining(", "));
String path = paths.stream()
.map(str -> str.startsWith("{") && str.endsWith("}") ? str : "\"" + str + "\"")
.collect(Collectors.joining(", "));
for (CodegenParameter param : op.pathParams) {
String str = paramToString("params", param, false, null);
path = path.replace("{" + param.paramName + "}", str);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,11 @@ private List<String> pathToServantRoute(String path, List<CodegenParameter> path
for (CodegenParameter param : pathParams) {
captureTypes.put(param.baseName, param.dataType);
}

// Properly handle root-only routes (#3256)
if (path.contentEquals("/")) {
return new ArrayList<>();
}

// Cut off the leading slash, if it is present.
if (path.startsWith("/")) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* 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.openapitools.codegen.elm;

import static com.google.common.collect.Lists.newArrayList;
import static java.util.Collections.emptyList;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.openapitools.codegen.ClientOptInput;
import org.openapitools.codegen.ClientOpts;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.MockDefaultGenerator;
import org.openapitools.codegen.languages.ElmClientCodegen;
import org.testng.annotations.Test;

import com.google.common.collect.ImmutableMap;

import io.swagger.parser.OpenAPIParser;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.parser.core.models.ParseOptions;

public class ElmClientCodegenTest {

@Test
public void testPostProcessRootEndpoint() {
// given
final ElmClientCodegen codegen = new ElmClientCodegen();

CodegenOperation rootOp = new CodegenOperation() {{ path = "/"; }};
List<CodegenOperation> ops = newArrayList(rootOp);

Map<String, Object> operations = new HashMap<>();
operations.put("operations", ImmutableMap
.<String, Object>builder()
.put("operation", ops)
.build());

// when
Map<String, Object> result = codegen.postProcessOperationsWithModels(operations, emptyList());

// then
assertEquals(result.size(), 2);
assertTrue(result.containsKey("operations"));
assertTrue(result.containsKey("elmImports"));

assertEquals(rootOp.path, "\"\"");
}

@Test
public void testGenerateRootEndpoint() throws IOException {
// given
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
String outputPath = output.getAbsolutePath().replace('\\', '/');

final ElmClientCodegen codegen = new ElmClientCodegen();
codegen.setOutputDir(output.getAbsolutePath());

OpenAPI openAPI = new OpenAPIParser()
.readLocation("src/test/resources/3_0/rootOperation.yaml", null, new ParseOptions())
.getOpenAPI();

ClientOpts opts = new ClientOpts();

ClientOptInput input = new ClientOptInput();
input.setOpenAPI(openAPI);
input.setConfig(codegen);
input.setOpts(opts);

// when
MockDefaultGenerator generator = new MockDefaultGenerator();
generator.opts(input).generate();

// then
assertFileContains(generator, outputPath + "/src/Request/Default.elm", "rootGet", "[\"\"]");
}

private static void assertFileContains(MockDefaultGenerator generator, String file, String... expected) {
String content = generator.getFiles().get(file);
assertNotNull(content, "The file \"" + file + "\" was not generated");
for (String line : expected) {
assertTrue(content.contains(line), "The file \"" + file + "\" does not contain \"" + line + "\"");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* 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.openapitools.codegen.haskellservant;

import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Arrays;

import org.openapitools.codegen.ClientOptInput;
import org.openapitools.codegen.ClientOpts;
import org.openapitools.codegen.MockDefaultGenerator;
import org.openapitools.codegen.languages.HaskellServantCodegen;
import org.testng.annotations.Test;

import io.swagger.parser.OpenAPIParser;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.parser.core.models.ParseOptions;

public class HaskellServantCodegenTest {

@Test
public void testGenerateRootEndpoint() throws IOException {
// given
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
String outputPath = output.getAbsolutePath().replace('\\', '/');

final HaskellServantCodegen codegen = new HaskellServantCodegen();
codegen.setOutputDir(output.getAbsolutePath());

OpenAPI openAPI = new OpenAPIParser()
.readLocation("src/test/resources/3_0/rootOperation.yaml", null, new ParseOptions())
.getOpenAPI();

ClientOpts opts = new ClientOpts();

ClientOptInput input = new ClientOptInput();
input.setOpenAPI(openAPI);
input.setConfig(codegen);
input.setOpts(opts);

// when
MockDefaultGenerator generator = new MockDefaultGenerator();
generator.opts(input).generate();

// then
assertFileNotContains(generator, outputPath + "/lib/RootOperation/API.hs", "\"\" :>");
}

private static void assertFileNotContains(MockDefaultGenerator generator, String file, String... expected) {
String content = generator.getFiles().get(file);
assertNotNull(content, "The file \"" + file + "\" was not generated");
for (String line : expected) {
assertFalse(content.contains(line), "The file \"" + file + "\" contains \"" + line + "\"");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
openapi: 3.0.0

info:
title: Root Operation
version: 1.0.0

paths:
/:
get:
summary: Simple root endpoint
responses:
204:
description: No response body
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4.0.0-SNAPSHOT
4.0.3-SNAPSHOT
12 changes: 8 additions & 4 deletions samples/client/petstore/elm-0.18/src/Data/ApiResponse.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
OpenAPI Petstore
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
OpenAPI spec version: 1.0.0
The version of the OpenAPI document: 1.0.0
NOTE: This file is auto generated by the openapi-generator.
https://github.com/openapitools/openapi-generator.git
Expand All @@ -21,9 +21,9 @@ import Json.Encode as Encode
{-| Describes the result of uploading an image resource
-}
type alias ApiResponse =
{ code : Maybe Int
, type_ : Maybe String
, message : Maybe String
{ code : Maybe (Int)
, type_ : Maybe (String)
, message : Maybe (String)
}


Expand All @@ -35,10 +35,14 @@ decoder =
|> optional "message" (Decode.nullable Decode.string) Nothing



encode : ApiResponse -> Encode.Value
encode model =
Encode.object
[ ( "code", Maybe.withDefault Encode.null (Maybe.map Encode.int model.code) )
, ( "type", Maybe.withDefault Encode.null (Maybe.map Encode.string model.type_) )
, ( "message", Maybe.withDefault Encode.null (Maybe.map Encode.string model.message) )

]


10 changes: 7 additions & 3 deletions samples/client/petstore/elm-0.18/src/Data/Category.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
OpenAPI Petstore
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
OpenAPI spec version: 1.0.0
The version of the OpenAPI document: 1.0.0
NOTE: This file is auto generated by the openapi-generator.
https://github.com/openapitools/openapi-generator.git
Expand All @@ -21,8 +21,8 @@ import Json.Encode as Encode
{-| A category for a pet
-}
type alias Category =
{ id : Maybe Int
, name : Maybe String
{ id : Maybe (Int)
, name : Maybe (String)
}


Expand All @@ -33,9 +33,13 @@ decoder =
|> optional "name" (Decode.nullable Decode.string) Nothing



encode : Category -> Encode.Value
encode model =
Encode.object
[ ( "id", Maybe.withDefault Encode.null (Maybe.map Encode.int model.id) )
, ( "name", Maybe.withDefault Encode.null (Maybe.map Encode.string model.name) )

]


22 changes: 15 additions & 7 deletions samples/client/petstore/elm-0.18/src/Data/Order_.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
OpenAPI Petstore
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
OpenAPI spec version: 1.0.0
The version of the OpenAPI document: 1.0.0
NOTE: This file is auto generated by the openapi-generator.
https://github.com/openapitools/openapi-generator.git
Expand All @@ -22,12 +22,12 @@ import Json.Encode as Encode
{-| An order for a pets from the pet store
-}
type alias Order_ =
{ id : Maybe Int
, petId : Maybe Int
, quantity : Maybe Int
, shipDate : Maybe DateTime
, status : Maybe Status
, complete : Maybe Bool
{ id : Maybe (Int)
, petId : Maybe (Int)
, quantity : Maybe (Int)
, shipDate : Maybe (DateTime)
, status : Maybe (Status)
, complete : Maybe (Bool)
}


Expand All @@ -37,6 +37,7 @@ type Status
| Delivered



decoder : Decoder Order_
decoder =
decode Order_
Expand All @@ -48,6 +49,7 @@ decoder =
|> optional "complete" (Decode.nullable Decode.bool) (Just False)



encode : Order_ -> Encode.Value
encode model =
Encode.object
Expand All @@ -57,9 +59,11 @@ encode model =
, ( "shipDate", Maybe.withDefault Encode.null (Maybe.map DateTime.encode model.shipDate) )
, ( "status", Maybe.withDefault Encode.null (Maybe.map encodeStatus model.status) )
, ( "complete", Maybe.withDefault Encode.null (Maybe.map Encode.bool model.complete) )

]



statusDecoder : Decoder Status
statusDecoder =
Decode.string
Expand All @@ -80,6 +84,7 @@ statusDecoder =
)



encodeStatus : Status -> Encode.Value
encodeStatus model =
case model of
Expand All @@ -91,3 +96,6 @@ encodeStatus model =

Delivered ->
Encode.string "delivered"



Loading

0 comments on commit 95ba952

Please sign in to comment.