import 'dart:io'; import 'package:koi_swagger_parser/koi_swagger_parser.dart'; import 'package:path/path.dart' as p; import 'package:test/test.dart'; void main() { group('generic union generation', () { test('生成 primitive oneOf 与可多分支匹配的 anyOf wrapper', () async { final tempDir = await Directory.systemTemp.createTemp( 'koi_swagger_parser_generic_union_', ); addTearDown(() => tempDir.delete(recursive: true)); final spec = File(p.join(tempDir.path, 'openapi.json')); await spec.writeAsString(r''' { "openapi": "3.1.0", "info": {"title": "generic unions", "version": "1"}, "paths": { "/api/v1/value": { "get": { "tags": ["value"], "operationId": "get_value", "responses": { "200": { "description": "ok", "content": { "application/json": { "schema": {"$ref": "#/components/schemas/UnionEnvelope"} } } } } } } }, "components": { "schemas": { "UnionEnvelope": { "type": "object", "required": ["value", "criteria"], "properties": { "value": {"$ref": "#/components/schemas/StringOrInteger"}, "criteria": {"$ref": "#/components/schemas/SearchCriteria"} } }, "StringOrInteger": { "oneOf": [ {"type": "string"}, {"type": "integer"} ] }, "SearchCriteria": { "anyOf": [ { "title": "ByName", "type": "object", "required": ["name"], "properties": {"name": {"type": "string"}} }, { "title": "ById", "type": "object", "required": ["id"], "properties": {"id": {"type": "integer"}} } ] } } } } '''); final outputDir = p.join(tempDir.path, 'lib', 'src'); final config = File(p.join(tempDir.path, 'koi_swagger_parser.yaml')); await config.writeAsString(''' input: swagger_urls: - url: ${spec.path} output: base_dir: $outputDir api_dir: ${p.join(outputDir, 'api')} models_dir: ${p.join(outputDir, 'models')} generation: api: response_wrapper: mode: passthrough formatting: run_dart_format: false '''); await const KoiSwaggerParser().generate(configPath: config.path); final oneOfFile = File( p.join(outputDir, 'models', 'result', 'string_or_integer.dart'), ); final oneOf = oneOfFile.readAsStringSync(); expect( oneOf, contains('factory KoiStringOrInteger.fromJson(Object? json)'), ); expect(oneOf, contains('if (json is String)')); expect(oneOf, contains('if (json is int)')); expect(oneOf, contains('if (matches.length != 1)')); expect( oneOf, contains( 'final class KoiStringOrIntegerString1 extends KoiStringOrInteger', ), ); final anyOfFile = File( p.join(outputDir, 'models', 'result', 'search_criteria.dart'), ); final anyOf = anyOfFile.readAsStringSync(); expect(anyOf, contains("json.containsKey('name')")); expect(anyOf, contains("json.containsKey('id')")); expect( anyOf, contains( 'final class KoiSearchCriteriaAnyOf extends KoiSearchCriteria', ), ); expect(anyOf, contains('final List matches')); for (final file in [oneOfFile, anyOfFile]) { final format = await Process.run(Platform.resolvedExecutable, [ 'format', '--output=none', file.path, ]); expect( format.exitCode, 0, reason: '${format.stdout}\n${format.stderr}', ); } }); }); }