Files
koi_swagger_parser/test/union_semantics_test.dart
mr.koi 454e6c51d7 Release 0.2.0
Complete OpenAPI 3.0/3.1 generation, diagnostics, lifecycle safety, enum and naming mappings, bilingual documentation, examples, and pub.dev release validation.
2026-07-31 16:47:39 +08:00

140 lines
3.8 KiB
Dart

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<KoiSearchCriteria> matches'));
for (final file in <File>[oneOfFile, anyOfFile]) {
final format = await Process.run(Platform.resolvedExecutable, <String>[
'format',
'--output=none',
file.path,
]);
expect(
format.exitCode,
0,
reason: '${format.stdout}\n${format.stderr}',
);
}
});
});
}