[Dart-dio] Add basic integration testing and fix compile errors (#8025)

* [dart-dio] Add basic integration test POM

This basically just fetches dependencies, runs the built_value generator and empty test cases. Even running empty test cases is more than is currently possible and at least finds compile errors.

There are compile errors atm which need to be fixed.

* [dart-dio] Fix missing BuiltSet import in models that use enums

* [dart-dio] Fix compile error when the return type is a Map

* the compile error was `serializerForType(Map<String, int>)` in `StoreApi` which needs to be  `serializerForType(Map)`
* use final instead of var in response handling

* [dart-dio] Generate docs after changes

* [dart-dio] Add integration test to CI execution list
This commit is contained in:
Peter Leibiger
2020-12-02 14:35:07 +01:00
committed by GitHub
parent 82c5021df2
commit 033d985cf7
26 changed files with 603 additions and 39 deletions

View File

@@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| ---------- | ------- |
|BuiltList|package:built_collection/built_collection.dart|
|BuiltMap|package:built_collection/built_collection.dart|
|BuiltSet|package:built_collection/built_collection.dart|
|JsonObject|package:built_value/json_object.dart|
|Uint8List|dart:typed_data|

View File

@@ -617,7 +617,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
return; // skip if DART_POST_PROCESS_FILE env variable is not defined
}
// only procees the following type (or we can simply rely on the file extension to check if it's a Dart file)
// only process the following type (or we can simply rely on the file extension to check if it's a Dart file)
Set<String> supportedFileType = Sets.newHashSet(
"supporting-mustache",
"model-test",

View File

@@ -51,7 +51,7 @@ public class DartDioClientCodegen extends DartClientCodegen {
private static final String IS_FORMAT_JSON = "jsonFormat";
private static final String CLIENT_NAME = "clientName";
private static Set<String> modelToIgnore = new HashSet<>();
private static final Set<String> modelToIgnore = new HashSet<>();
static {
modelToIgnore.add("datetime");
@@ -71,10 +71,6 @@ public class DartDioClientCodegen extends DartClientCodegen {
embeddedTemplateDir = "dart-dio";
this.setTemplateDir(embeddedTemplateDir);
//no tests at this time
modelTestTemplateFiles.clear();
apiTestTemplateFiles.clear();
cliOptions.add(new CliOption(NULLABLE_FIELDS, "Is the null fields should be in the JSON payload"));
CliOption dateLibrary = new CliOption(DATE_LIBRARY, "Option. Date library to use").defaultValue(this.getDateLibrary());
Map<String, String> dateOptions = new HashMap<>();
@@ -88,6 +84,7 @@ public class DartDioClientCodegen extends DartClientCodegen {
typeMapping.put("AnyType", "Object");
importMapping.put("BuiltList", "package:built_collection/built_collection.dart");
importMapping.put("BuiltSet", "package:built_collection/built_collection.dart");
importMapping.put("BuiltMap", "package:built_collection/built_collection.dart");
importMapping.put("JsonObject", "package:built_value/json_object.dart");
importMapping.put("Uint8List", "dart:typed_data");
@@ -109,7 +106,6 @@ public class DartDioClientCodegen extends DartClientCodegen {
this.nullableFields = nullableFields;
}
@Override
public String getName() {
return "dart-dio";
@@ -316,6 +312,11 @@ public class DartDioClientCodegen extends DartClientCodegen {
if (property.dataType.contains("JsonObject")) {
model.imports.add("JsonObject");
}
if (property.isEnum) {
// enums are generated with built_value and make use of BuiltSet
model.imports.add("BuiltSet");
}
}
@Override
@@ -378,5 +379,4 @@ public class DartDioClientCodegen extends DartClientCodegen {
return objs;
}
}

View File

@@ -95,18 +95,23 @@ class {{classname}} {
){{#returnType}}.then((response) {
{{#isResponseFile}}
var data = response.data;
final data = response.data;
{{/isResponseFile}}
{{^isResponseFile}}
{{#isArray}}
final FullType type = const FullType(BuiltList, const [const FullType({{returnBaseType}})]);
BuiltList<{{returnBaseType}}> dataList = _serializers.deserialize(response.data is String ? jsonDecode(response.data) : response.data, specifiedType: type);
var data = dataList.toList();
{{/isArray}}
{{^isArray}}
var serializer = _serializers.serializerForType({{{returnType}}});
var data = _serializers.deserializeWith<{{{returnType}}}>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
{{/isArray}}
{{#isArray}}
final FullType type = const FullType(BuiltList, const [const FullType({{returnBaseType}})]);
final BuiltList<{{returnBaseType}}> dataList = _serializers.deserialize(response.data is String ? jsonDecode(response.data) : response.data, specifiedType: type);
final data = dataList.toList();
{{/isArray}}
{{^isArray}}
{{#isMap}}
final serializer = _serializers.serializerForType(Map);
{{/isMap}}
{{^isMap}}
final serializer = _serializers.serializerForType({{{returnType}}});
{{/isMap}}
final data = _serializers.deserializeWith<{{{returnType}}}>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
{{/isArray}}
{{/isResponseFile}}
return Response<{{{returnType}}}>(

View File

@@ -0,0 +1,29 @@
import 'package:{{pubName}}/api.dart';
import 'package:{{pubName}}/api/{{classFilename}}.dart';
import 'package:test/test.dart';
{{#operations}}
/// tests for {{{classname}}}
void main() {
final instance = {{{clientName}}}().get{{{classname}}}();
group({{{classname}}}, () {
{{#operation}}
{{#summary}}
// {{{.}}}
//
{{/summary}}
{{#notes}}
// {{{.}}}
//
{{/notes}}
//{{#returnType}}Future<{{{returnType}}}> {{/returnType}}{{^returnType}}Future {{/returnType}}{{{operationId}}}({{#allParams}}{{#required}}{{{dataType}}} {{{paramName}}}{{^-last}}, {{/-last}}{{/required}}{{/allParams}}{{#hasOptionalParams}}{ {{#allParams}}{{^required}}{{{dataType}}} {{{paramName}}}{{^-last}}, {{/-last}}{{/required}}{{/allParams}} }{{/hasOptionalParams}}) async
test('test {{{operationId}}}', () async {
// TODO
});
{{/operation}}
});
}
{{/operations}}

View File

@@ -0,0 +1,28 @@
{{#models}}
{{#model}}
import 'package:{{pubName}}/model/{{classFilename}}.dart';
import 'package:test/test.dart';
// tests for {{{classname}}}
void main() {
{{^isEnum}}
final instance = {{{classname}}}();
{{/isEnum}}
group({{{classname}}}, () {
{{#vars}}
{{#description}}
// {{{description}}}
{{/description}}
// {{{dataType}}} {{{name}}}{{#defaultValue}} (default value: {{{.}}}){{/defaultValue}}
test('to test the property `{{{name}}}`', () async {
// TODO
});
{{/vars}}
});
}
{{/model}}
{{/models}}

View File

@@ -13,4 +13,5 @@ dependencies:
dev_dependencies:
built_value_generator: ^7.1.0
build_runner: ^1.7.1
test: ^1.3.0

View File

@@ -1350,6 +1350,7 @@
<module>samples/server/petstore/go-api-server</module>
<module>samples/server/petstore/go-gin-api-server</module>
<module>samples/client/petstore/dart2/petstore</module>
<module>samples/client/petstore/dart-dio</module>
<module>samples/client/petstore/dart-jaguar/openapi</module>
<module>samples/client/petstore/dart-jaguar/flutter_petstore/openapi</module>
</modules>

View File

@@ -27,6 +27,9 @@ doc/api/
# (Library packages only! Remove pattern if developing an application package)
pubspec.lock
# Don't commit *.g.dart files which are genrated during integration tests
lib/**/*.g.dart
# Dont commit files and directories created by other development environments.
# For example, if your development environment creates any of the following files,
# consider putting them in a global ignore file:

View File

@@ -21,3 +21,6 @@
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md
# Don't regenerate .gitignore as it contains customizations for generated dart files
.gitignore

View File

@@ -1,4 +1,3 @@
.gitignore
README.md
analysis_options.yaml
doc/ApiResponse.md

View File

@@ -126,9 +126,9 @@ class PetApi {
onReceiveProgress: onReceiveProgress,
).then((response) {
final FullType type = const FullType(BuiltList, const [const FullType(Pet)]);
BuiltList<Pet> dataList = _serializers.deserialize(response.data is String ? jsonDecode(response.data) : response.data, specifiedType: type);
var data = dataList.toList();
final FullType type = const FullType(BuiltList, const [const FullType(Pet)]);
final BuiltList<Pet> dataList = _serializers.deserialize(response.data is String ? jsonDecode(response.data) : response.data, specifiedType: type);
final data = dataList.toList();
return Response<List<Pet>>(
data: data,
@@ -177,9 +177,9 @@ class PetApi {
onReceiveProgress: onReceiveProgress,
).then((response) {
final FullType type = const FullType(BuiltList, const [const FullType(Pet)]);
BuiltList<Pet> dataList = _serializers.deserialize(response.data is String ? jsonDecode(response.data) : response.data, specifiedType: type);
var data = dataList.toList();
final FullType type = const FullType(BuiltList, const [const FullType(Pet)]);
final BuiltList<Pet> dataList = _serializers.deserialize(response.data is String ? jsonDecode(response.data) : response.data, specifiedType: type);
final data = dataList.toList();
return Response<List<Pet>>(
data: data,
@@ -227,8 +227,8 @@ class PetApi {
onReceiveProgress: onReceiveProgress,
).then((response) {
var serializer = _serializers.serializerForType(Pet);
var data = _serializers.deserializeWith<Pet>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
final serializer = _serializers.serializerForType(Pet);
final data = _serializers.deserializeWith<Pet>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
return Response<Pet>(
data: data,
@@ -361,8 +361,8 @@ class PetApi {
onReceiveProgress: onReceiveProgress,
).then((response) {
var serializer = _serializers.serializerForType(ApiResponse);
var data = _serializers.deserializeWith<ApiResponse>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
final serializer = _serializers.serializerForType(ApiResponse);
final data = _serializers.deserializeWith<ApiResponse>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
return Response<ApiResponse>(
data: data,

View File

@@ -83,8 +83,8 @@ class StoreApi {
onReceiveProgress: onReceiveProgress,
).then((response) {
var serializer = _serializers.serializerForType(Map<String, int>);
var data = _serializers.deserializeWith<Map<String, int>>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
final serializer = _serializers.serializerForType(Map);
final data = _serializers.deserializeWith<Map<String, int>>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
return Response<Map<String, int>>(
data: data,
@@ -132,8 +132,8 @@ class StoreApi {
onReceiveProgress: onReceiveProgress,
).then((response) {
var serializer = _serializers.serializerForType(Order);
var data = _serializers.deserializeWith<Order>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
final serializer = _serializers.serializerForType(Order);
final data = _serializers.deserializeWith<Order>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
return Response<Order>(
data: data,
@@ -184,8 +184,8 @@ class StoreApi {
onReceiveProgress: onReceiveProgress,
).then((response) {
var serializer = _serializers.serializerForType(Order);
var data = _serializers.deserializeWith<Order>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
final serializer = _serializers.serializerForType(Order);
final data = _serializers.deserializeWith<Order>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
return Response<Order>(
data: data,

View File

@@ -199,8 +199,8 @@ class UserApi {
onReceiveProgress: onReceiveProgress,
).then((response) {
var serializer = _serializers.serializerForType(User);
var data = _serializers.deserializeWith<User>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
final serializer = _serializers.serializerForType(User);
final data = _serializers.deserializeWith<User>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
return Response<User>(
data: data,
@@ -250,8 +250,8 @@ class UserApi {
onReceiveProgress: onReceiveProgress,
).then((response) {
var serializer = _serializers.serializerForType(String);
var data = _serializers.deserializeWith<String>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
final serializer = _serializers.serializerForType(String);
final data = _serializers.deserializeWith<String>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
return Response<String>(
data: data,

View File

@@ -1,3 +1,4 @@
import 'package:built_collection/built_collection.dart';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';

View File

@@ -0,0 +1,88 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.openapitools</groupId>
<artifactId>DartDioPetstoreClientTests</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<name>DartDio Petstore Client</name>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>export-dartfmt</id>
<phase>pre-install-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>export</executable>
<arguments>
<argument>DART_FMT_PATH=/usr/local/bin/dartfmt</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>pub-get</id>
<phase>pre-integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>pub</executable>
<arguments>
<argument>get</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>pub-run-build-runner</id>
<phase>pre-integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>pub</executable>
<arguments>
<argument>run</argument>
<argument>build_runner</argument>
<argument>build</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>pub-test</id>
<phase>integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>pub</executable>
<arguments>
<argument>run</argument>
<argument>test</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -10,4 +10,5 @@ dependencies:
dev_dependencies:
built_value_generator: ^7.1.0
build_runner: ^1.7.1
test: ^1.3.0

View File

@@ -0,0 +1,27 @@
import 'package:openapi/model/api_response.dart';
import 'package:test/test.dart';
// tests for ApiResponse
void main() {
final instance = ApiResponse();
group(ApiResponse, () {
// int code (default value: null)
test('to test the property `code`', () async {
// TODO
});
// String type (default value: null)
test('to test the property `type`', () async {
// TODO
});
// String message (default value: null)
test('to test the property `message`', () async {
// TODO
});
});
}

View File

@@ -0,0 +1,22 @@
import 'package:openapi/model/category.dart';
import 'package:test/test.dart';
// tests for Category
void main() {
final instance = Category();
group(Category, () {
// int id (default value: null)
test('to test the property `id`', () async {
// TODO
});
// String name (default value: null)
test('to test the property `name`', () async {
// TODO
});
});
}

View File

@@ -0,0 +1,43 @@
import 'package:openapi/model/order.dart';
import 'package:test/test.dart';
// tests for Order
void main() {
final instance = Order();
group(Order, () {
// int id (default value: null)
test('to test the property `id`', () async {
// TODO
});
// int petId (default value: null)
test('to test the property `petId`', () async {
// TODO
});
// int quantity (default value: null)
test('to test the property `quantity`', () async {
// TODO
});
// DateTime shipDate (default value: null)
test('to test the property `shipDate`', () async {
// TODO
});
// Order Status
// String status (default value: null)
test('to test the property `status`', () async {
// TODO
});
// bool complete (default value: false)
test('to test the property `complete`', () async {
// TODO
});
});
}

View File

@@ -0,0 +1,74 @@
import 'package:openapi/api.dart';
import 'package:openapi/api/pet_api.dart';
import 'package:test/test.dart';
/// tests for PetApi
void main() {
final instance = Openapi().getPetApi();
group(PetApi, () {
// Add a new pet to the store
//
//Future addPet(Pet body) async
test('test addPet', () async {
// TODO
});
// Deletes a pet
//
//Future deletePet(int petId, { String apiKey }) async
test('test deletePet', () async {
// TODO
});
// Finds Pets by status
//
// Multiple status values can be provided with comma separated strings
//
//Future<List<Pet>> findPetsByStatus(List<String> status) async
test('test findPetsByStatus', () async {
// TODO
});
// Finds Pets by tags
//
// Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
//
//Future<List<Pet>> findPetsByTags(List<String> tags) async
test('test findPetsByTags', () async {
// TODO
});
// Find pet by ID
//
// Returns a single pet
//
//Future<Pet> getPetById(int petId) async
test('test getPetById', () async {
// TODO
});
// Update an existing pet
//
//Future updatePet(Pet body) async
test('test updatePet', () async {
// TODO
});
// Updates a pet in the store with form data
//
//Future updatePetWithForm(int petId, { String name, String status }) async
test('test updatePetWithForm', () async {
// TODO
});
// uploads an image
//
//Future<ApiResponse> uploadFile(int petId, { String additionalMetadata, Uint8List file }) async
test('test uploadFile', () async {
// TODO
});
});
}

View File

@@ -0,0 +1,43 @@
import 'package:openapi/model/pet.dart';
import 'package:test/test.dart';
// tests for Pet
void main() {
final instance = Pet();
group(Pet, () {
// int id (default value: null)
test('to test the property `id`', () async {
// TODO
});
// Category category (default value: null)
test('to test the property `category`', () async {
// TODO
});
// String name (default value: null)
test('to test the property `name`', () async {
// TODO
});
// BuiltList<String> photoUrls (default value: const [])
test('to test the property `photoUrls`', () async {
// TODO
});
// BuiltList<Tag> tags (default value: const [])
test('to test the property `tags`', () async {
// TODO
});
// pet status in the store
// String status (default value: null)
test('to test the property `status`', () async {
// TODO
});
});
}

View File

@@ -0,0 +1,46 @@
import 'package:openapi/api.dart';
import 'package:openapi/api/store_api.dart';
import 'package:test/test.dart';
/// tests for StoreApi
void main() {
final instance = Openapi().getStoreApi();
group(StoreApi, () {
// Delete purchase order by ID
//
// For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
//
//Future deleteOrder(String orderId) async
test('test deleteOrder', () async {
// TODO
});
// Returns pet inventories by status
//
// Returns a map of status codes to quantities
//
//Future<Map<String, int>> getInventory() async
test('test getInventory', () async {
// TODO
});
// Find purchase order by ID
//
// For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions
//
//Future<Order> getOrderById(int orderId) async
test('test getOrderById', () async {
// TODO
});
// Place an order for a pet
//
//Future<Order> placeOrder(Order body) async
test('test placeOrder', () async {
// TODO
});
});
}

View File

@@ -0,0 +1,22 @@
import 'package:openapi/model/tag.dart';
import 'package:test/test.dart';
// tests for Tag
void main() {
final instance = Tag();
group(Tag, () {
// int id (default value: null)
test('to test the property `id`', () async {
// TODO
});
// String name (default value: null)
test('to test the property `name`', () async {
// TODO
});
});
}

View File

@@ -0,0 +1,74 @@
import 'package:openapi/api.dart';
import 'package:openapi/api/user_api.dart';
import 'package:test/test.dart';
/// tests for UserApi
void main() {
final instance = Openapi().getUserApi();
group(UserApi, () {
// Create user
//
// This can only be done by the logged in user.
//
//Future createUser(User body) async
test('test createUser', () async {
// TODO
});
// Creates list of users with given input array
//
//Future createUsersWithArrayInput(List<User> body) async
test('test createUsersWithArrayInput', () async {
// TODO
});
// Creates list of users with given input array
//
//Future createUsersWithListInput(List<User> body) async
test('test createUsersWithListInput', () async {
// TODO
});
// Delete user
//
// This can only be done by the logged in user.
//
//Future deleteUser(String username) async
test('test deleteUser', () async {
// TODO
});
// Get user by user name
//
//Future<User> getUserByName(String username) async
test('test getUserByName', () async {
// TODO
});
// Logs user into the system
//
//Future<String> loginUser(String username, String password) async
test('test loginUser', () async {
// TODO
});
// Logs out current logged in user session
//
//Future logoutUser() async
test('test logoutUser', () async {
// TODO
});
// Updated user
//
// This can only be done by the logged in user.
//
//Future updateUser(String username, User body) async
test('test updateUser', () async {
// TODO
});
});
}

View File

@@ -0,0 +1,53 @@
import 'package:openapi/model/user.dart';
import 'package:test/test.dart';
// tests for User
void main() {
final instance = User();
group(User, () {
// int id (default value: null)
test('to test the property `id`', () async {
// TODO
});
// String username (default value: null)
test('to test the property `username`', () async {
// TODO
});
// String firstName (default value: null)
test('to test the property `firstName`', () async {
// TODO
});
// String lastName (default value: null)
test('to test the property `lastName`', () async {
// TODO
});
// String email (default value: null)
test('to test the property `email`', () async {
// TODO
});
// String password (default value: null)
test('to test the property `password`', () async {
// TODO
});
// String phone (default value: null)
test('to test the property `phone`', () async {
// TODO
});
// User Status
// int userStatus (default value: null)
test('to test the property `userStatus`', () async {
// TODO
});
});
}