这是indexloc提供的服务,不要输入任何密码
Skip to content

Fix date property types #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
.fvm/

# Integration Test
/integration_test/petstore/petstore_api
/integration_test/imposter.jar
/integration_test/petstore/petstore_api
/integration_test/music_streaming/music_streaming_api
/integration_test/gov/gov_api

# Dependencies
/pubspec.lock
38 changes: 38 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,44 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## 2025-06-15

### Changes

---

Packages with breaking changes:

- There are no breaking changes in this release.

Packages with other changes:

- [`tonik` - `v0.0.6`](#tonik---v006)
- [`tonik_core` - `v0.0.6`](#tonik_core---v006)
- [`tonik_generate` - `v0.0.6`](#tonik_generate---v006)
- [`tonik_parse` - `v0.0.6`](#tonik_parse---v006)
- [`tonik_util` - `v0.0.6`](#tonik_util---v006)

---

#### `tonik` - `v0.0.6`

#### `tonik_core` - `v0.0.6`

#### `tonik_generate` - `v0.0.6`

- **FIX**: proper handle dates.
- **FIX**: priority for exlict defined names of schemas.
- **FIX**: prio for explicitly defined names.
- **FIX**: proper hash code for classes with >20 properties.

#### `tonik_parse` - `v0.0.6`

#### `tonik_util` - `v0.0.6`

- **FIX**: proper handle dates.


## 2025-06-02

### Changes
Expand Down
7 changes: 7 additions & 0 deletions integration_test/gov/gov_test/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# https://dart.dev/guides/libraries/private-files
# Created by `dart pub`
.dart_tool/

# Avoid committing pubspec.lock for library packages; see
# https://dart.dev/guides/libraries/private-files#pubspeclock.
pubspec.lock
30 changes: 30 additions & 0 deletions integration_test/gov/gov_test/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# This file configures the static analysis results for your project (errors,
# warnings, and lints).
#
# This enables the 'recommended' set of lints from `package:lints`.
# This set helps identify many issues that may lead to problems when running
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
# style and format.
#
# If you want a smaller set of lints you can change this to specify
# 'package:lints/core.yaml'. These are just the most critical lints
# (the recommended set includes the core lints).
# The core lints are also what is used by pub.dev for scoring packages.

include: package:lints/recommended.yaml

# Uncomment the following section to specify additional rules.

# linter:
# rules:
# - camel_case_types

# analyzer:
# exclude:
# - path/to/excluded/files/**

# For more information about the core and recommended set of lints, see
# https://dart.dev/go/core-lints

# For additional information about configuring this file, see
# https://dart.dev/guides/language/analysis-options
7 changes: 7 additions & 0 deletions integration_test/gov/gov_test/imposter/imposter-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"plugin": "openapi",
"specFile": "../../openapi.yaml",
"response": {
"scriptFile": "response.groovy"
}
}
7 changes: 7 additions & 0 deletions integration_test/gov/gov_test/imposter/response.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Get the response status from the request header
def responseStatus = context.request.headers['X-Response-Status'] ?: '200'

// Set the response status code and use the OpenAPI specification
respond()
.withStatusCode(Integer.parseInt(responseStatus))
.usingDefaultBehaviour()
19 changes: 19 additions & 0 deletions integration_test/gov/gov_test/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: gov_test
description: A starting point for Dart libraries or applications.
version: 1.0.0
publish_to: none

environment:
sdk: ^3.8.0

dependencies:
dio: ^5.8.0
gov_api:
path: ../gov_api
path: ^1.8.3
tonik_util: ^0.0.6

dev_dependencies:
test: ^1.24.0
very_good_analysis: ^9.0.0

120 changes: 120 additions & 0 deletions integration_test/gov/gov_test/test/default_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import 'package:dio/dio.dart';
import 'package:gov_api/gov_api.dart';
import 'package:test/test.dart';
import 'package:tonik_util/tonik_util.dart';

import 'test_helper.dart';

void main() {
const port = 8080;
const baseUrl = 'http://localhost:$port';

late ImposterServer imposterServer;

setUpAll(() async {
imposterServer = ImposterServer(port: port);
await setupImposterServer(imposterServer);
});

DefaultApi buildAlbumsApi({required String responseStatus}) {
return DefaultApi(
CustomServer(
baseUrl: baseUrl,
serverConfig: ServerConfig(
baseOptions: BaseOptions(
headers: {'X-Response-Status': responseStatus},
),
),
),
);
}

group('findForms', () {
test('200', () async {
final defaultApi = buildAlbumsApi(responseStatus: '200');

final response = await defaultApi.findForms(query: '10-10EZ');

expect(response, isA<TonikSuccess<FindFormsResponse>>());
final success = response as TonikSuccess<FindFormsResponse>;
expect(success.response.statusCode, 200);
expect(success.value, isA<FindFormsResponse200>());

final value = success.value as FindFormsResponse200;
expect(value.body, isA<FormsGet200Body>());

final body = value.body;
expect(body.data, isA<List<FormsIndex>>());

final formIndex = body.data.first;
expect(formIndex.attributes?.benefitCategories, isA<List<FormsIndexAttributesBenefitCategoriesArray>>());
expect(formIndex.id, isA<String?>());
expect(formIndex.$type, isA<String?>());

final attributes = formIndex.attributes;
final benefitCategory = attributes?.benefitCategories?.first;
expect(benefitCategory?.name, isA<String?>());
expect(benefitCategory?.description, isA<String?>());

expect(attributes?.deletedAt, isA<DateTime?>());
expect(attributes?.firstIssuedOn, isA<Date?>());
expect(attributes?.formDetailsUrl, isA<String?>());
expect(attributes?.formName, isA<String?>());
expect(attributes?.formToolIntro, isA<String?>());
expect(attributes?.formToolUrl, isA<String?>());
expect(attributes?.formType, isA<String?>());
expect(attributes?.formUsage, isA<String?>());
expect(attributes?.language, isA<String?>());
expect(attributes?.lastRevisionOn, isA<Date?>());
expect(attributes?.lastSha256Change, isA<Date?>());
expect(attributes?.pages, isA<int?>());
expect(attributes?.relatedForms, isA<List<String>?>());
expect(attributes?.sha256, isA<String?>());
expect(attributes?.title, isA<String?>());
expect(attributes?.url, isA<String?>());
expect(attributes?.vaFormAdministration, isA<String?>());
expect(attributes?.validPdf, isA<bool?>());
});

test('401', () async {
final defaultApi = buildAlbumsApi(responseStatus: '401');

final response = await defaultApi.findForms();

expect(response, isA<TonikSuccess<FindFormsResponse>>());
final success = response as TonikSuccess<FindFormsResponse>;

expect(success.response.statusCode, 401);
expect(success.value, isA<FindFormsResponse401>());

final value = success.value as FindFormsResponse401;
expect(value.body, isA<FormsGet401Body>());

final body = value.body;
expect(body.message, isA<String?>());
});

test('429', () async {
final defaultApi = buildAlbumsApi(responseStatus: '429');

final response = await defaultApi.findForms();

expect(response, isA<TonikSuccess<FindFormsResponse>>());
final success = response as TonikSuccess<FindFormsResponse>;

expect(success.response.statusCode, 429);
expect(success.value, isA<FindFormsResponse429>());

final value = success.value as FindFormsResponse429;
expect(value.body, isA<FormsGet429Body>());
});

test('unexpected status code', () async {
final defaultApi = buildAlbumsApi(responseStatus: '500');

final response = await defaultApi.findForms();

expect(response, isA<TonikError<FindFormsResponse>>());
});
});
}
87 changes: 87 additions & 0 deletions integration_test/gov/gov_test/test/test_helper.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import 'dart:convert';
import 'dart:io';

import 'package:path/path.dart' as path;
import 'package:test/test.dart';

class ImposterServer {
ImposterServer({required this.port});

Process? _process;
final int port;

Future<void> start() async {
final imposterJar = path.join(
Directory.current.parent.parent.path,
'imposter.jar',
);

if (!File(imposterJar).existsSync()) {
throw Exception(
'Imposter JAR not found at $imposterJar. Please download it first.',
);
}

_process = await Process.start(
'java',
[
'-jar',
imposterJar,
'--listenPort',
port.toString(),
'--configDir',
path.join(Directory.current.path, 'imposter'),
'--plugin',
'openapi',
'--plugin',
'rest',
],
environment: {
...Platform.environment,
'IMPOSTER_LOG_LEVEL': 'DEBUG',
},
);

_process!.stdout.transform(const Utf8Decoder()).listen((data) {
print('Imposter stdout: $data');
});
_process!.stderr.transform(const Utf8Decoder()).listen((data) {
print('Imposter stderr: $data');
});

await _waitForImposterReady();
}

Future<bool> _waitForImposterReady({int timeoutSec = 10}) async {
final deadline = DateTime.now().add(Duration(seconds: timeoutSec));
final client = HttpClient();

while (DateTime.now().isBefore(deadline)) {
try {
final request = await client.getUrl(
Uri.parse('http://localhost:$port'),
);
await request.close();

return true; // No exception means the server is ready.
} on SocketException catch (_) {
// ignore
}
await Future<void>.delayed(const Duration(milliseconds: 300));
}
return false;
}

Future<void> stop() async {
if (_process != null) {
_process!.kill();
await _process!.exitCode;
_process = null;
}
}
}

Future<void> setupImposterServer(ImposterServer server) async {
await server.start();
addTearDown(() => server.stop());
}
Loading