diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 6ab2d05..4a4e565 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -8,7 +8,7 @@ on: jobs: Test: - name: 'openapi_sec' + name: 'openapi_spec_tests' runs-on: ubuntu-22.04 steps: diff --git a/Makefile b/Makefile index 23aafad..abbfe8b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ .DEFAULT_TARGET: help .PHONY: build test coverage docs example +TEST_ARGS ?= + help: @echo "Package Makefile" @@ -28,11 +30,14 @@ example: rm -rf build dart run example/example.dart +# Example use: +# make test +# make test TEST_ARGS="-n Unions" test: @dart pub get && \ rm -rf test/tmp && \ clear && \ - dart test && \ + dart test $(TEST_ARGS) && \ make build-test format: diff --git a/test/openai/test.dart b/test/openai/test.dart index 78d865d..1e96746 100644 --- a/test/openai/test.dart +++ b/test/openai/test.dart @@ -37,7 +37,7 @@ void main() { spec.toJsonFile(destination: testJson); }); - // / Test code generation of OpenAPI spec defined models + /// Test code generation of OpenAPI spec defined models test('Generate Schema Code', () async { await spec.generate( package: 'openai', diff --git a/test/openapi_spec_test.dart b/test/openapi_spec_test.dart index 7372d15..8c8d59c 100644 --- a/test/openapi_spec_test.dart +++ b/test/openapi_spec_test.dart @@ -4,6 +4,7 @@ import 'petstore/test.dart' as petstore; import 'oas_examples/test.dart' as oas_examples; import 'chromadb/test.dart' as chromadb; import 'openai/test.dart' as openai; +import 'unions/test.dart' as unions; void main() { // Ensure a clean test tmp directory @@ -17,4 +18,5 @@ void main() { oas_examples.main(); chromadb.main(); openai.main(); + unions.main(); } diff --git a/test/unions/test.dart b/test/unions/test.dart new file mode 100644 index 0000000..a577fc3 --- /dev/null +++ b/test/unions/test.dart @@ -0,0 +1,120 @@ +import 'dart:io'; +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; + +import 'package:openapi_spec/openapi_spec.dart'; + +void main() { + final tmp = Directory( + p.join('test', 'tmp', 'unions'), + ); + + final truthJson = p.join('test', 'unions', 'unions.json'); + final testJson = p.join(tmp.path, 'unions.json'); + + final genSchemaDir = p.join(tmp.path, 'gen_schema'); + final genSchemaOptionsDir = p.join(tmp.path, 'gen_schema_options'); + final genSchemaSingleDir = p.join(tmp.path, 'gen_schema_single'); + + late OpenApi spec; + + group('Unions', () { + setUp(() { + spec = OpenApi.fromFile(source: truthJson); + if (!tmp.existsSync()) { + tmp.createSync(recursive: true); + } + }); + + /// Test JSON to Dart [OpenApi] object parsing + test('JSON -> Dart', () { + // Ensure generated file can be read back into Dart + final spec = OpenApi.fromFile( + source: truthJson, + ); + + // Write the Dart representation back to JSON + spec.toJsonFile(destination: testJson); + }); + + /// Test schema generation (multi-file) + test('Generate Schema Code', () async { + await spec.generate( + package: 'unions', + quiet: true, + destination: genSchemaDir, + ); + final expectedFiles = [ + 'alpha_training.dart', + 'beta_training.dart', + 'alpha_transform.dart', + 'beta_transform.dart', + 'gamma_transform.dart', + 'group_transform.dart', + 'schema.dart', + 'training_setup.dart', + 'union_training.dart', + 'union_transform.dart', + 'union_transform2.dart', + ]; + final genFiles = Directory(p.join(genSchemaDir, 'schema')) + .listSync() + .map((e) => p.basename(e.path)); + for (final file in expectedFiles) { + expect(genFiles, contains(file)); + } + }); + + /// Test schema generation (single file) + test('Generate Schema Code', () async { + await spec.generate( + package: 'unions', + quiet: true, + destination: genSchemaSingleDir, + schemaOptions: SchemaGeneratorOptions( + singleFile: true, + ), + ); + final genFiles = + Directory(p.join(genSchemaSingleDir, 'schema')).listSync(); + expect(genFiles.length, 1); + }); + + /// Test schema generation with union customizations + test('Generate Schema Code (Options)', () async { + await spec.generate( + package: 'unions', + quiet: true, + destination: genSchemaOptionsDir, + schemaOptions: SchemaGeneratorOptions( + onSchemaUnionName: (name, unions) { + if (name == 'UnionTransform' && unions.length == 3) { + return 'UnionTransformMember'; + } + return name; + }, + ), + ); + final expectedFiles = [ + 'alpha_training.dart', + 'beta_training.dart', + 'alpha_transform.dart', + 'beta_transform.dart', + 'gamma_transform.dart', + 'group_transform.dart', + 'schema.dart', + 'training_setup.dart', + 'union_training.dart', + 'union_transform.dart', + // This file should be renamed from default "union_transform2.dart" + 'union_transform_member.dart', + ]; + final genFiles = Directory(p.join(genSchemaOptionsDir, 'schema')) + .listSync() + .map((e) => p.basename(e.path)); + for (final file in expectedFiles) { + expect(genFiles, contains(file)); + } + }); + }); +} diff --git a/test/unions/unions.json b/test/unions/unions.json new file mode 100644 index 0000000..d871f43 --- /dev/null +++ b/test/unions/unions.json @@ -0,0 +1,265 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "Unions schema", + "description": "Schema with lots of unions", + "version": "1.0.0" + }, + "paths": { + + }, + "components": { + "schemas": { + "TrainingSetup": { + "title": "TrainingSetup", + "required": [ + "name", + "training" + ], + "type": "object", + "properties": { + "name": { + "title": "Name", + "type": "string", + "description": "Name of the training." + }, + "description": { + "title": "Description", + "type": "string", + "description": "Description of the training setup." + }, + "training": { + "title": "Training", + "anyOf": [ + { + "$ref": "#/components/schemas/AlphaTraining" + }, + { + "$ref": "#/components/schemas/BetaTraining" + } + ], + "description": "The type of training to perform." + } + } + }, + "AlphaTraining": { + "title": "AlphaTraining", + "required": [ + "data_ids" + ], + "type": "object", + "properties": { + "data_ids": { + "title": "Data Ids", + "type": "array", + "items": { + "type": "string" + }, + "description": "Data sources." + }, + "alpha_kind": { + "title": "Alpha Kind", + "enum": [ + "alpha" + ], + "type": "string", + "description": "Alpha training kind", + "default": "alpha" + }, + "x_transform": { + "title": "X Transform", + "anyOf": [ + { + "$ref": "#/components/schemas/AlphaTransform" + }, + { + "$ref": "#/components/schemas/BetaTransform" + }, + { + "$ref": "#/components/schemas/GammaTransform" + }, + { + "$ref": "#/components/schemas/GroupTransform" + } + ], + "description": "Transform to apply to X data.", + "default": { + "kind": "alpha" + } + }, + "y_transform": { + "title": "Y Transform", + "anyOf": [ + { + "$ref": "#/components/schemas/AlphaTransform" + }, + { + "$ref": "#/components/schemas/BetaTransform" + }, + { + "$ref": "#/components/schemas/GammaTransform" + }, + { + "$ref": "#/components/schemas/GroupTransform" + } + ], + "description": "Transform to apply to Y data.", + "default": { + "kind": "alpha" + } + } + } + }, + "BetaTraining": { + "title": "BetaTraining", + "required": [ + "data_ids" + ], + "type": "object", + "properties": { + "data_ids": { + "title": "Data Ids", + "type": "array", + "items": { + "type": "string" + }, + "description": "Data sources." + }, + "beta_kind": { + "title": "Beta Kind", + "enum": [ + "beta" + ], + "type": "string", + "description": "Beta training kind", + "default": "beta" + }, + "x_transform": { + "title": "X Transform", + "anyOf": [ + { + "$ref": "#/components/schemas/AlphaTransform" + }, + { + "$ref": "#/components/schemas/BetaTransform" + }, + { + "$ref": "#/components/schemas/GammaTransform" + }, + { + "$ref": "#/components/schemas/GroupTransform" + } + ], + "description": "Transform to apply to X data.", + "default": { + "kind": "alpha" + } + }, + "y_transform": { + "title": "Y Transform", + "anyOf": [ + { + "$ref": "#/components/schemas/AlphaTransform" + }, + { + "$ref": "#/components/schemas/BetaTransform" + }, + { + "$ref": "#/components/schemas/GammaTransform" + }, + { + "$ref": "#/components/schemas/GroupTransform" + } + ], + "description": "Transform to apply to Y data.", + "default": { + "kind": "alpha" + } + } + } + }, + "AlphaTransform": { + "title": "AlphaTransform", + "type": "object", + "properties": { + "kind": { + "title": "Kind", + "enum": [ + "alpha" + ], + "type": "string", + "description": "Standard alpha transform", + "default": "alpha" + } + } + }, + "BetaTransform": { + "title": "BetaTransform", + "type": "object", + "properties": { + "kind": { + "title": "Kind", + "enum": [ + "beta" + ], + "type": "string", + "description": "Standard beta transform", + "default": "beta" + } + } + }, + "GammaTransform": { + "title": "GammaTransform", + "type": "object", + "properties": { + "kind": { + "title": "Kind", + "enum": [ + "gamma" + ], + "type": "string", + "description": "Standard gamma transform", + "default": "gamma" + } + } + }, + "GroupTransform": { + "title": "GroupTransform", + "required": [ + "transforms" + ], + "type": "object", + "properties": { + "kind": { + "title": "Transform Kind", + "enum": [ + "group" + ], + "type": "string", + "description": "A group of transforms.", + "default": "group" + }, + "transforms": { + "title": "Transforms", + "minItems": 1, + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/AlphaTransform" + }, + { + "$ref": "#/components/schemas/BetaTransform" + }, + { + "$ref": "#/components/schemas/GammaTransform" + } + ] + }, + "description": "The group of transforms." + } + } + } + } + } +} \ No newline at end of file