From 131412784a715d4c912be5bce422e31042d4e176 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 03:45:38 +0000 Subject: [PATCH 01/19] Initial plan From 7bbb66e0ce73419cd0facb751d06eddc79d09efa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 03:52:38 +0000 Subject: [PATCH 02/19] Add comprehensive test coverage for version resolution Add tests for: - _dependenciesFromJson parsing in pubspec.dart (string versions, map versions, path/git dependencies, invalid versions, null dependencies, mixed formats) - Integration version constraint collection in config.dart (from pubspec.yaml and pubspec.lock) - Version resolution priority and edge cases Co-authored-by: AlexV525 <15884415+AlexV525@users.noreply.github.com> --- packages/core/test/config_test.dart | 217 +++++++++++++++++ packages/core/test/settings_test.dart | 227 ++++++++++++++++++ .../pubspec_integration_versions.lock | 29 +++ .../pubspec_integration_versions.yaml | 21 ++ ...pubspec_integration_versions_rive_014.lock | 21 ++ ...pubspec_integration_versions_rive_014.yaml | 18 ++ 6 files changed, 533 insertions(+) create mode 100644 packages/core/test/config_test.dart create mode 100644 packages/core/test_resources/pubspec_integration_versions.lock create mode 100644 packages/core/test_resources/pubspec_integration_versions.yaml create mode 100644 packages/core/test_resources/pubspec_integration_versions_rive_014.lock create mode 100644 packages/core/test_resources/pubspec_integration_versions_rive_014.yaml diff --git a/packages/core/test/config_test.dart b/packages/core/test/config_test.dart new file mode 100644 index 00000000..d8de16ff --- /dev/null +++ b/packages/core/test/config_test.dart @@ -0,0 +1,217 @@ +import 'dart:io'; + +import 'package:flutter_gen_core/generators/integrations/lottie_integration.dart'; +import 'package:flutter_gen_core/generators/integrations/rive_integration.dart'; +import 'package:flutter_gen_core/generators/integrations/svg_integration.dart'; +import 'package:flutter_gen_core/settings/config.dart'; +import 'package:pub_semver/pub_semver.dart'; +import 'package:test/test.dart'; + +void main() { + group('Config integration version resolution', () { + test('resolves versions from pubspec.lock', () { + final pubspecFile = File( + 'test_resources/pubspec_integration_versions.yaml', + ); + final config = loadPubspecConfig(pubspecFile); + + // Check that versions are resolved from pubspec.lock + expect( + config.integrationResolvedVersions[RiveIntegration], + equals(Version(0, 13, 5)), + ); + expect( + config.integrationResolvedVersions[SvgIntegration], + equals(Version(2, 0, 9)), + ); + expect( + config.integrationResolvedVersions[LottieIntegration], + equals(Version(5, 1, 0)), + ); + }); + + test('resolves version constraints from pubspec.yaml', () { + final pubspecFile = File( + 'test_resources/pubspec_integration_versions.yaml', + ); + final config = loadPubspecConfig(pubspecFile); + + // Check that constraints are resolved from pubspec.yaml + expect( + config.integrationVersionConstraints[RiveIntegration], + equals(VersionConstraint.parse('^0.13.0')), + ); + expect( + config.integrationVersionConstraints[SvgIntegration], + equals(VersionConstraint.parse('^2.0.0')), + ); + expect( + config.integrationVersionConstraints[LottieIntegration], + equals(VersionConstraint.parse('^5.0.0')), + ); + }); + + test('resolves Rive 0.14.0 versions correctly', () { + final pubspecFile = File( + 'test_resources/pubspec_integration_versions_rive_014.yaml', + ); + final config = loadPubspecConfig(pubspecFile); + + // Check that Rive 0.14.0+ version is resolved + expect( + config.integrationResolvedVersions[RiveIntegration], + equals(Version(0, 14, 1)), + ); + expect( + config.integrationVersionConstraints[RiveIntegration], + equals(VersionConstraint.parse('^0.14.0')), + ); + + // Check that flutter_svg is also resolved + expect( + config.integrationResolvedVersions[SvgIntegration], + equals(Version(2, 0, 10)), + ); + expect( + config.integrationVersionConstraints[SvgIntegration], + equals(VersionConstraint.parse('>=2.0.0 <3.0.0')), + ); + }); + + test('handles missing pubspec.lock gracefully', () { + // Use a pubspec without a corresponding .lock file + final pubspecFile = File( + 'test_resources/pubspec_assets_rive_integrations.yaml', + ); + final config = loadPubspecConfig(pubspecFile); + + // Should have empty or no resolved versions + // but should not crash + expect(config, isNotNull); + expect(config.integrationResolvedVersions, isA()); + expect(config.integrationVersionConstraints, isA()); + }); + + test('handles dependencies without version constraints', () { + final pubspecFile = File( + 'test_resources/pubspec_integration_versions.yaml', + ); + final config = loadPubspecConfig(pubspecFile); + + // Packages not in dependencies should not be in the maps + expect( + config.integrationVersionConstraints.containsKey(null), + isFalse, + ); + }); + + test('integration versions are used in AssetsGenConfig', () { + final pubspecFile = File( + 'test_resources/pubspec_integration_versions.yaml', + ); + final config = loadPubspecConfig(pubspecFile); + + // Verify that the resolved versions and constraints are available + expect(config.integrationResolvedVersions, isNotEmpty); + expect(config.integrationVersionConstraints, isNotEmpty); + + // Verify they can be passed to generators + expect( + config.integrationResolvedVersions[RiveIntegration], + isA(), + ); + expect( + config.integrationVersionConstraints[RiveIntegration], + isA(), + ); + }); + + test('version resolution with only constraint and no lock', () { + // Create a temporary pubspec file without a lock + final tempDir = Directory.systemTemp.createTempSync('flutter_gen_test'); + try { + final tempPubspec = File('${tempDir.path}/pubspec.yaml'); + tempPubspec.writeAsStringSync(''' +name: test_no_lock +environment: + sdk: ^3.0.0 +dependencies: + rive: ^0.13.0 +flutter_gen: + output: lib/gen/ + integrations: + rive: true +flutter: + assets: + - assets/ +'''); + + final config = loadPubspecConfig(tempPubspec); + + // Should have constraint but no resolved version + expect( + config.integrationVersionConstraints[RiveIntegration], + equals(VersionConstraint.parse('^0.13.0')), + ); + expect( + config.integrationResolvedVersions[RiveIntegration], + isNull, + ); + } finally { + tempDir.deleteSync(recursive: true); + } + }); + + test('version resolution with lock but no constraint', () { + // This tests the case where pubspec.lock has a version + // but pubspec.yaml doesn't specify a constraint (e.g., path dependency) + final tempDir = Directory.systemTemp.createTempSync('flutter_gen_test'); + try { + final tempPubspec = File('${tempDir.path}/pubspec.yaml'); + tempPubspec.writeAsStringSync(''' +name: test_lock_only +environment: + sdk: ^3.0.0 +dependencies: + rive: + path: ../rive +flutter_gen: + output: lib/gen/ + integrations: + rive: true +flutter: + assets: + - assets/ +'''); + + final tempLock = File('${tempDir.path}/pubspec.lock'); + tempLock.writeAsStringSync(''' +packages: + rive: + dependency: "direct main" + description: + path: "../rive" + relative: true + source: path + version: "0.13.5" +sdks: + dart: ">=3.0.0 <4.0.0" +'''); + + final config = loadPubspecConfig(tempPubspec); + + // Should have resolved version but no constraint + expect( + config.integrationResolvedVersions[RiveIntegration], + equals(Version(0, 13, 5)), + ); + expect( + config.integrationVersionConstraints[RiveIntegration], + isNull, + ); + } finally { + tempDir.deleteSync(recursive: true); + } + }); + }); +} diff --git a/packages/core/test/settings_test.dart b/packages/core/test/settings_test.dart index 3629b1f4..b2a32b2c 100644 --- a/packages/core/test/settings_test.dart +++ b/packages/core/test/settings_test.dart @@ -4,7 +4,9 @@ import 'package:flutter_gen_core/settings/flavored_asset.dart'; import 'package:flutter_gen_core/settings/pubspec.dart'; import 'package:flutter_gen_core/utils/error.dart' show InvalidSettingsException; +import 'package:pub_semver/pub_semver.dart'; import 'package:test/test.dart'; +import 'package:yaml/yaml.dart'; void main() { group(AssetType, () { @@ -116,4 +118,229 @@ void main() { ); }); }); + + group('Pubspec.dependenciesVersionConstraint', () { + test('parses string version constraints', () { + final yaml = loadYaml(''' +name: test +environment: + sdk: ^3.0.0 +dependencies: + rive: ^0.13.0 + flutter_svg: ^2.0.0 + lottie: ">=1.0.0 <2.0.0" +flutter_gen: + output: lib/gen/ +flutter: + assets: + - assets/ +'''); + final pubspec = Pubspec.fromJson(yaml); + + expect(pubspec.dependenciesVersionConstraint['rive'], isNotNull); + expect( + pubspec.dependenciesVersionConstraint['rive'], + equals(VersionConstraint.parse('^0.13.0')), + ); + + expect(pubspec.dependenciesVersionConstraint['flutter_svg'], isNotNull); + expect( + pubspec.dependenciesVersionConstraint['flutter_svg'], + equals(VersionConstraint.parse('^2.0.0')), + ); + + expect(pubspec.dependenciesVersionConstraint['lottie'], isNotNull); + expect( + pubspec.dependenciesVersionConstraint['lottie'], + equals(VersionConstraint.parse('>=1.0.0 <2.0.0')), + ); + }); + + test('parses map with version key', () { + final yaml = loadYaml(''' +name: test +environment: + sdk: ^3.0.0 +dependencies: + rive: + version: ^0.14.0 + flutter_svg: + version: ">=2.0.0 <3.0.0" +flutter_gen: + output: lib/gen/ +flutter: + assets: + - assets/ +'''); + final pubspec = Pubspec.fromJson(yaml); + + expect(pubspec.dependenciesVersionConstraint['rive'], isNotNull); + expect( + pubspec.dependenciesVersionConstraint['rive'], + equals(VersionConstraint.parse('^0.14.0')), + ); + + expect(pubspec.dependenciesVersionConstraint['flutter_svg'], isNotNull); + expect( + pubspec.dependenciesVersionConstraint['flutter_svg'], + equals(VersionConstraint.parse('>=2.0.0 <3.0.0')), + ); + }); + + test('handles path dependencies without version', () { + final yaml = loadYaml(''' +name: test +environment: + sdk: ^3.0.0 +dependencies: + rive: + path: ../rive + flutter_svg: ^2.0.0 +flutter_gen: + output: lib/gen/ +flutter: + assets: + - assets/ +'''); + final pubspec = Pubspec.fromJson(yaml); + + // Path dependency should be null since no version constraint + expect(pubspec.dependenciesVersionConstraint['rive'], isNull); + + // String version should still work + expect(pubspec.dependenciesVersionConstraint['flutter_svg'], isNotNull); + expect( + pubspec.dependenciesVersionConstraint['flutter_svg'], + equals(VersionConstraint.parse('^2.0.0')), + ); + }); + + test('handles git dependencies without version', () { + final yaml = loadYaml(''' +name: test +environment: + sdk: ^3.0.0 +dependencies: + rive: + git: + url: https://github.com/example/rive.git + ref: main + lottie: ^5.0.0 +flutter_gen: + output: lib/gen/ +flutter: + assets: + - assets/ +'''); + final pubspec = Pubspec.fromJson(yaml); + + // Git dependency should be null since no version constraint + expect(pubspec.dependenciesVersionConstraint['rive'], isNull); + + // String version should still work + expect(pubspec.dependenciesVersionConstraint['lottie'], isNotNull); + expect( + pubspec.dependenciesVersionConstraint['lottie'], + equals(VersionConstraint.parse('^5.0.0')), + ); + }); + + test('handles invalid version strings gracefully', () { + final yaml = loadYaml(''' +name: test +environment: + sdk: ^3.0.0 +dependencies: + rive: invalid_version + flutter_svg: ^2.0.0 +flutter_gen: + output: lib/gen/ +flutter: + assets: + - assets/ +'''); + final pubspec = Pubspec.fromJson(yaml); + + // Invalid version should be null + expect(pubspec.dependenciesVersionConstraint['rive'], isNull); + + // Valid version should work + expect(pubspec.dependenciesVersionConstraint['flutter_svg'], isNotNull); + }); + + test('handles dependencies with version key containing invalid version', () { + final yaml = loadYaml(''' +name: test +environment: + sdk: ^3.0.0 +dependencies: + rive: + version: invalid_version + lottie: ^5.0.0 +flutter_gen: + output: lib/gen/ +flutter: + assets: + - assets/ +'''); + final pubspec = Pubspec.fromJson(yaml); + + // Invalid version in map should be null + expect(pubspec.dependenciesVersionConstraint['rive'], isNull); + + // Valid string version should work + expect(pubspec.dependenciesVersionConstraint['lottie'], isNotNull); + }); + + test('handles null dependencies', () { + final yaml = loadYaml(''' +name: test +environment: + sdk: ^3.0.0 +flutter_gen: + output: lib/gen/ +flutter: + assets: + - assets/ +'''); + final pubspec = Pubspec.fromJson(yaml); + + // Should return empty map for null dependencies + expect(pubspec.dependenciesVersionConstraint, isEmpty); + }); + + test('handles mixed dependency formats', () { + final yaml = loadYaml(''' +name: test +environment: + sdk: ^3.0.0 +dependencies: + rive: ^0.13.0 + flutter_svg: + version: ^2.0.0 + lottie: + path: ../lottie + another_package: + git: + url: https://github.com/example/package.git +flutter_gen: + output: lib/gen/ +flutter: + assets: + - assets/ +'''); + final pubspec = Pubspec.fromJson(yaml); + + expect( + pubspec.dependenciesVersionConstraint['rive'], + equals(VersionConstraint.parse('^0.13.0')), + ); + expect( + pubspec.dependenciesVersionConstraint['flutter_svg'], + equals(VersionConstraint.parse('^2.0.0')), + ); + expect(pubspec.dependenciesVersionConstraint['lottie'], isNull); + expect(pubspec.dependenciesVersionConstraint['another_package'], isNull); + }); + }); } diff --git a/packages/core/test_resources/pubspec_integration_versions.lock b/packages/core/test_resources/pubspec_integration_versions.lock new file mode 100644 index 00000000..e2f8a807 --- /dev/null +++ b/packages/core/test_resources/pubspec_integration_versions.lock @@ -0,0 +1,29 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + rive: + dependency: "direct main" + description: + name: rive + sha256: "abc123" + url: "https://pub.dev" + source: hosted + version: "0.13.5" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "def456" + url: "https://pub.dev" + source: hosted + version: "2.0.9" + lottie: + dependency: "direct main" + description: + name: lottie + sha256: "ghi789" + url: "https://pub.dev" + source: hosted + version: "5.1.0" +sdks: + dart: ">=3.0.0 <4.0.0" diff --git a/packages/core/test_resources/pubspec_integration_versions.yaml b/packages/core/test_resources/pubspec_integration_versions.yaml new file mode 100644 index 00000000..222cb0f9 --- /dev/null +++ b/packages/core/test_resources/pubspec_integration_versions.yaml @@ -0,0 +1,21 @@ +name: test_integration_versions + +environment: + sdk: ^3.0.0 + +dependencies: + rive: ^0.13.0 + flutter_svg: ^2.0.0 + lottie: + version: ^5.0.0 + +flutter_gen: + output: lib/gen/ + integrations: + rive: true + flutter_svg: true + lottie: true + +flutter: + assets: + - assets/ diff --git a/packages/core/test_resources/pubspec_integration_versions_rive_014.lock b/packages/core/test_resources/pubspec_integration_versions_rive_014.lock new file mode 100644 index 00000000..8009d48b --- /dev/null +++ b/packages/core/test_resources/pubspec_integration_versions_rive_014.lock @@ -0,0 +1,21 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + rive: + dependency: "direct main" + description: + name: rive + sha256: "xyz123" + url: "https://pub.dev" + source: hosted + version: "0.14.1" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "uvw456" + url: "https://pub.dev" + source: hosted + version: "2.0.10" +sdks: + dart: ">=3.0.0 <4.0.0" diff --git a/packages/core/test_resources/pubspec_integration_versions_rive_014.yaml b/packages/core/test_resources/pubspec_integration_versions_rive_014.yaml new file mode 100644 index 00000000..7bd8c58d --- /dev/null +++ b/packages/core/test_resources/pubspec_integration_versions_rive_014.yaml @@ -0,0 +1,18 @@ +name: test_integration_versions_rive_014 + +environment: + sdk: ^3.0.0 + +dependencies: + rive: ^0.14.0 + flutter_svg: ">=2.0.0 <3.0.0" + +flutter_gen: + output: lib/gen/ + integrations: + rive: true + flutter_svg: true + +flutter: + assets: + - assets/ From 45a3991034a7bec0142d90eaf439db1758fe7437 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 03:53:45 +0000 Subject: [PATCH 03/19] Add integration tests for version resolution in assets generator Test version resolution with various constraint formats and validate the integration with AssetsGenConfig Co-authored-by: AlexV525 <15884415+AlexV525@users.noreply.github.com> --- .../test/assets_gen_integrations_test.dart | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/packages/core/test/assets_gen_integrations_test.dart b/packages/core/test/assets_gen_integrations_test.dart index dd397d7e..4e4ba454 100644 --- a/packages/core/test/assets_gen_integrations_test.dart +++ b/packages/core/test/assets_gen_integrations_test.dart @@ -459,5 +459,77 @@ void main() { isTrue, ); }); + + test('Integration version resolution in AssetsGenConfig', () { + // Test that version resolution is properly integrated into assets generation + // This validates the full flow from config loading to integration creation + + // Create a RiveIntegration with both resolved version and constraint + final integrationWithBoth = RiveIntegration( + '', + resolvedVersion: Version(0, 13, 0), + resolvedVersionConstraint: VersionConstraint.parse('^0.14.0'), + ); + // Should prefer resolvedVersion over resolvedVersionConstraint + expect(integrationWithBoth, isA()); + + // Create a RiveIntegration with only resolvedVersion + final integrationVersionOnly = RiveIntegration( + '', + resolvedVersion: Version(0, 14, 0), + ); + expect(integrationVersionOnly, isA()); + + // Create a RiveIntegration with only resolvedVersionConstraint + final integrationConstraintOnly = RiveIntegration( + '', + resolvedVersionConstraint: VersionConstraint.parse('^0.14.0'), + ); + expect(integrationConstraintOnly, isA()); + }); + + test('Version resolution with various constraint formats', () { + // Test with ^0.13.x constraint (should use Classic) + final caretOld = RiveIntegration( + '', + resolvedVersionConstraint: VersionConstraint.parse('^0.13.5'), + ); + expect(caretOld, isA()); + + // Test with ^0.14.x constraint (should use 0140) + final caretNew = RiveIntegration( + '', + resolvedVersionConstraint: VersionConstraint.parse('^0.14.1'), + ); + expect(caretNew, isA()); + + // Test with >= constraint that includes 0.14.0 + final rangeIncludesNew = RiveIntegration( + '', + resolvedVersionConstraint: VersionConstraint.parse('>=0.13.0 <1.0.0'), + ); + expect(rangeIncludesNew, isA()); + + // Test with >= constraint that excludes 0.14.0 + final rangeExcludesNew = RiveIntegration( + '', + resolvedVersionConstraint: VersionConstraint.parse('>=0.13.0 <0.14.0'), + ); + expect(rangeExcludesNew, isA()); + + // Test with exact version < 0.14.0 + final exactOld = RiveIntegration( + '', + resolvedVersion: Version(0, 13, 99), + ); + expect(exactOld, isA()); + + // Test with exact version >= 0.14.0 + final exactNew = RiveIntegration( + '', + resolvedVersion: Version(0, 14, 0), + ); + expect(exactNew, isA()); + }); }); } From 6ebe3fba88ab5544b978241430f0dee5724e93dc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 03:55:26 +0000 Subject: [PATCH 04/19] Fix test issues from code review - Replace meaningless null key check with proper validation of expected integration types - Clarify comment about version resolution priority Co-authored-by: AlexV525 <15884415+AlexV525@users.noreply.github.com> --- .../test/assets_gen_integrations_test.dart | 4 +++- packages/core/test/config_test.dart | 23 ++++++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/packages/core/test/assets_gen_integrations_test.dart b/packages/core/test/assets_gen_integrations_test.dart index 4e4ba454..e96b7bf2 100644 --- a/packages/core/test/assets_gen_integrations_test.dart +++ b/packages/core/test/assets_gen_integrations_test.dart @@ -465,12 +465,14 @@ void main() { // This validates the full flow from config loading to integration creation // Create a RiveIntegration with both resolved version and constraint + // When resolvedVersion is 0.13.0 (< 0.14.0), it should use Classic + // even if resolvedVersionConstraint would allow 0.14.0 final integrationWithBoth = RiveIntegration( '', resolvedVersion: Version(0, 13, 0), resolvedVersionConstraint: VersionConstraint.parse('^0.14.0'), ); - // Should prefer resolvedVersion over resolvedVersionConstraint + // resolvedVersion takes priority: 0.13.0 < 0.14.0 => Classic expect(integrationWithBoth, isA()); // Create a RiveIntegration with only resolvedVersion diff --git a/packages/core/test/config_test.dart b/packages/core/test/config_test.dart index d8de16ff..7f8666c3 100644 --- a/packages/core/test/config_test.dart +++ b/packages/core/test/config_test.dart @@ -92,17 +92,28 @@ void main() { expect(config.integrationVersionConstraints, isA()); }); - test('handles dependencies without version constraints', () { + test('verifies only expected integration types are present', () { final pubspecFile = File( 'test_resources/pubspec_integration_versions.yaml', ); final config = loadPubspecConfig(pubspecFile); - // Packages not in dependencies should not be in the maps - expect( - config.integrationVersionConstraints.containsKey(null), - isFalse, - ); + // Verify that only integration types from the registry are in the maps + for (final key in config.integrationVersionConstraints.keys) { + expect( + [RiveIntegration, SvgIntegration, LottieIntegration].contains(key), + isTrue, + reason: 'Unexpected integration type: $key', + ); + } + + for (final key in config.integrationResolvedVersions.keys) { + expect( + [RiveIntegration, SvgIntegration, LottieIntegration].contains(key), + isTrue, + reason: 'Unexpected integration type: $key', + ); + } }); test('integration versions are used in AssetsGenConfig', () { From c0986b4daa40663f277b7096d166a1b1df6c76cd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 03:57:07 +0000 Subject: [PATCH 05/19] Improve test maintainability based on code review - Use consistent dependency format in test resources - Import and use integrationPackages registry instead of hardcoding types Co-authored-by: AlexV525 <15884415+AlexV525@users.noreply.github.com> --- packages/core/test/config_test.dart | 7 +++++-- .../core/test_resources/pubspec_integration_versions.yaml | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/core/test/config_test.dart b/packages/core/test/config_test.dart index 7f8666c3..7cdfab68 100644 --- a/packages/core/test/config_test.dart +++ b/packages/core/test/config_test.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:flutter_gen_core/generators/integrations/lottie_integration.dart'; import 'package:flutter_gen_core/generators/integrations/rive_integration.dart'; import 'package:flutter_gen_core/generators/integrations/svg_integration.dart'; +import 'package:flutter_gen_core/generators/registry.dart'; import 'package:flutter_gen_core/settings/config.dart'; import 'package:pub_semver/pub_semver.dart'; import 'package:test/test.dart'; @@ -99,9 +100,11 @@ void main() { final config = loadPubspecConfig(pubspecFile); // Verify that only integration types from the registry are in the maps + final expectedTypes = integrationPackages.keys.toList(); + for (final key in config.integrationVersionConstraints.keys) { expect( - [RiveIntegration, SvgIntegration, LottieIntegration].contains(key), + expectedTypes.contains(key), isTrue, reason: 'Unexpected integration type: $key', ); @@ -109,7 +112,7 @@ void main() { for (final key in config.integrationResolvedVersions.keys) { expect( - [RiveIntegration, SvgIntegration, LottieIntegration].contains(key), + expectedTypes.contains(key), isTrue, reason: 'Unexpected integration type: $key', ); diff --git a/packages/core/test_resources/pubspec_integration_versions.yaml b/packages/core/test_resources/pubspec_integration_versions.yaml index 222cb0f9..fecd6e60 100644 --- a/packages/core/test_resources/pubspec_integration_versions.yaml +++ b/packages/core/test_resources/pubspec_integration_versions.yaml @@ -6,8 +6,7 @@ environment: dependencies: rive: ^0.13.0 flutter_svg: ^2.0.0 - lottie: - version: ^5.0.0 + lottie: ^5.0.0 flutter_gen: output: lib/gen/ From 3d8146a33ba6949042f6420193031367a54b4c94 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 04:15:37 +0000 Subject: [PATCH 06/19] Fix test resource paths to follow pubspec.lock naming convention Moved test resources into subdirectories with standard pubspec.yaml/pubspec.lock names. This fixes the issue where loadPubspecConfig expects pubspec.lock in the same directory as pubspec.yaml, not with custom names. Co-authored-by: AlexV525 <15884415+AlexV525@users.noreply.github.com> --- packages/core/test/config_test.dart | 10 +++---- .../pubspec.yaml} | 0 .../pubspec.yaml} | 0 .../pubspec_integration_versions.lock | 29 ------------------- ...pubspec_integration_versions_rive_014.lock | 21 -------------- 5 files changed, 5 insertions(+), 55 deletions(-) rename packages/core/test_resources/{pubspec_integration_versions.yaml => integration_versions/pubspec.yaml} (100%) rename packages/core/test_resources/{pubspec_integration_versions_rive_014.yaml => integration_versions_rive_014/pubspec.yaml} (100%) delete mode 100644 packages/core/test_resources/pubspec_integration_versions.lock delete mode 100644 packages/core/test_resources/pubspec_integration_versions_rive_014.lock diff --git a/packages/core/test/config_test.dart b/packages/core/test/config_test.dart index 7cdfab68..7f4baabb 100644 --- a/packages/core/test/config_test.dart +++ b/packages/core/test/config_test.dart @@ -12,7 +12,7 @@ void main() { group('Config integration version resolution', () { test('resolves versions from pubspec.lock', () { final pubspecFile = File( - 'test_resources/pubspec_integration_versions.yaml', + 'test_resources/integration_versions/pubspec.yaml', ); final config = loadPubspecConfig(pubspecFile); @@ -33,7 +33,7 @@ void main() { test('resolves version constraints from pubspec.yaml', () { final pubspecFile = File( - 'test_resources/pubspec_integration_versions.yaml', + 'test_resources/integration_versions/pubspec.yaml', ); final config = loadPubspecConfig(pubspecFile); @@ -54,7 +54,7 @@ void main() { test('resolves Rive 0.14.0 versions correctly', () { final pubspecFile = File( - 'test_resources/pubspec_integration_versions_rive_014.yaml', + 'test_resources/integration_versions_rive_014/pubspec.yaml', ); final config = loadPubspecConfig(pubspecFile); @@ -95,7 +95,7 @@ void main() { test('verifies only expected integration types are present', () { final pubspecFile = File( - 'test_resources/pubspec_integration_versions.yaml', + 'test_resources/integration_versions/pubspec.yaml', ); final config = loadPubspecConfig(pubspecFile); @@ -121,7 +121,7 @@ void main() { test('integration versions are used in AssetsGenConfig', () { final pubspecFile = File( - 'test_resources/pubspec_integration_versions.yaml', + 'test_resources/integration_versions/pubspec.yaml', ); final config = loadPubspecConfig(pubspecFile); diff --git a/packages/core/test_resources/pubspec_integration_versions.yaml b/packages/core/test_resources/integration_versions/pubspec.yaml similarity index 100% rename from packages/core/test_resources/pubspec_integration_versions.yaml rename to packages/core/test_resources/integration_versions/pubspec.yaml diff --git a/packages/core/test_resources/pubspec_integration_versions_rive_014.yaml b/packages/core/test_resources/integration_versions_rive_014/pubspec.yaml similarity index 100% rename from packages/core/test_resources/pubspec_integration_versions_rive_014.yaml rename to packages/core/test_resources/integration_versions_rive_014/pubspec.yaml diff --git a/packages/core/test_resources/pubspec_integration_versions.lock b/packages/core/test_resources/pubspec_integration_versions.lock deleted file mode 100644 index e2f8a807..00000000 --- a/packages/core/test_resources/pubspec_integration_versions.lock +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - rive: - dependency: "direct main" - description: - name: rive - sha256: "abc123" - url: "https://pub.dev" - source: hosted - version: "0.13.5" - flutter_svg: - dependency: "direct main" - description: - name: flutter_svg - sha256: "def456" - url: "https://pub.dev" - source: hosted - version: "2.0.9" - lottie: - dependency: "direct main" - description: - name: lottie - sha256: "ghi789" - url: "https://pub.dev" - source: hosted - version: "5.1.0" -sdks: - dart: ">=3.0.0 <4.0.0" diff --git a/packages/core/test_resources/pubspec_integration_versions_rive_014.lock b/packages/core/test_resources/pubspec_integration_versions_rive_014.lock deleted file mode 100644 index 8009d48b..00000000 --- a/packages/core/test_resources/pubspec_integration_versions_rive_014.lock +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - rive: - dependency: "direct main" - description: - name: rive - sha256: "xyz123" - url: "https://pub.dev" - source: hosted - version: "0.14.1" - flutter_svg: - dependency: "direct main" - description: - name: flutter_svg - sha256: "uvw456" - url: "https://pub.dev" - source: hosted - version: "2.0.10" -sdks: - dart: ">=3.0.0 <4.0.0" From 757f0ef0e15f1a900ace3d122c5ae6685bd7962f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 04:16:21 +0000 Subject: [PATCH 07/19] Add pubspec.lock files for integration version tests Force-add the lock files that were excluded by gitignore. These test resources need lock files to test version resolution. Co-authored-by: AlexV525 <15884415+AlexV525@users.noreply.github.com> --- .../integration_versions/pubspec.lock | 29 +++++++++++++++++++ .../pubspec.lock | 21 ++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 packages/core/test_resources/integration_versions/pubspec.lock create mode 100644 packages/core/test_resources/integration_versions_rive_014/pubspec.lock diff --git a/packages/core/test_resources/integration_versions/pubspec.lock b/packages/core/test_resources/integration_versions/pubspec.lock new file mode 100644 index 00000000..e2f8a807 --- /dev/null +++ b/packages/core/test_resources/integration_versions/pubspec.lock @@ -0,0 +1,29 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + rive: + dependency: "direct main" + description: + name: rive + sha256: "abc123" + url: "https://pub.dev" + source: hosted + version: "0.13.5" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "def456" + url: "https://pub.dev" + source: hosted + version: "2.0.9" + lottie: + dependency: "direct main" + description: + name: lottie + sha256: "ghi789" + url: "https://pub.dev" + source: hosted + version: "5.1.0" +sdks: + dart: ">=3.0.0 <4.0.0" diff --git a/packages/core/test_resources/integration_versions_rive_014/pubspec.lock b/packages/core/test_resources/integration_versions_rive_014/pubspec.lock new file mode 100644 index 00000000..8009d48b --- /dev/null +++ b/packages/core/test_resources/integration_versions_rive_014/pubspec.lock @@ -0,0 +1,21 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + rive: + dependency: "direct main" + description: + name: rive + sha256: "xyz123" + url: "https://pub.dev" + source: hosted + version: "0.14.1" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "uvw456" + url: "https://pub.dev" + source: hosted + version: "2.0.10" +sdks: + dart: ">=3.0.0 <4.0.0" From f02b25252c83364c53454e0990e7b006c693a1eb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 04:18:54 +0000 Subject: [PATCH 08/19] Fix pubspec.lock path resolution to use full parent path Changed from basename(pubspecFile.parent.path) to pubspecFile.parent.path to correctly resolve pubspec.lock location. The basename() call was stripping directory structure, causing lock files in subdirectories to not be found. Co-authored-by: AlexV525 <15884415+AlexV525@users.noreply.github.com> --- packages/core/lib/settings/config.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/lib/settings/config.dart b/packages/core/lib/settings/config.dart index 68cacd18..7a0fe25b 100644 --- a/packages/core/lib/settings/config.dart +++ b/packages/core/lib/settings/config.dart @@ -105,7 +105,7 @@ Config loadPubspecConfig(File pubspecFile, {File? buildFile}) { final pubspec = Pubspec.fromJson(mergedMap); final pubspecLockFile = File( - normalize(join(basename(pubspecFile.parent.path), 'pubspec.lock')), + normalize(join(pubspecFile.parent.path, 'pubspec.lock')), ); final pubspecLockContent = switch (pubspecLockFile.existsSync()) { true => pubspecLockFile.readAsStringSync(), From 7f88429a001fd4402940b671eb10c788be944ba4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 04:19:19 +0000 Subject: [PATCH 09/19] Fix analysis_options.yaml path resolution Apply same fix to analysis_options.yaml path - use full parent path instead of basename to correctly locate the file. Co-authored-by: AlexV525 <15884415+AlexV525@users.noreply.github.com> --- packages/core/lib/settings/config.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/lib/settings/config.dart b/packages/core/lib/settings/config.dart index 7a0fe25b..682787c0 100644 --- a/packages/core/lib/settings/config.dart +++ b/packages/core/lib/settings/config.dart @@ -130,7 +130,7 @@ Config loadPubspecConfig(File pubspecFile, {File? buildFile}) { } final analysisOptionsFile = File( - normalize(join(basename(pubspecFile.parent.path), 'analysis_options.yaml')), + normalize(join(pubspecFile.parent.path, 'analysis_options.yaml')), ); final analysisOptionsContent = switch (analysisOptionsFile.existsSync()) { true => analysisOptionsFile.readAsStringSync(), From 519f3dac809e60999b5b78bf2939c75bc66c68aa Mon Sep 17 00:00:00 2001 From: Alex Li Date: Wed, 4 Mar 2026 10:34:35 +0800 Subject: [PATCH 10/19] Fix prettier formats --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 210d0c57..ccff1b23 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "private": true, "author": "wasabeef", "scripts": { - "format": "prettier --config prettier.config.js --write '**/*.+(md|yml|yaml|json)'", + "format": "prettier --config prettier.config.js --write \"**/*.+(md|yml|yaml|json)\"", "prepare": "husky install" }, "lint-staged": { @@ -21,5 +21,5 @@ "prettier": "^3.0.3", "prettier-plugin-packagejson": "^2.4.5" }, - "packageManager": "pnpm@10.22.0" + "packageManager": "pnpm@10.30.3" } From fed3eb9a44c3bbda833c9d96132d17b1ec089612 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Wed, 4 Mar 2026 10:35:05 +0800 Subject: [PATCH 11/19] Fix Melos --- .github/workflows/build.yml | 17 ++++++++--------- .github/workflows/publish.yml | 4 ++-- .github/workflows/release.yml | 3 +-- melos.yaml | 8 +++++--- .../integration_versions_rive_014/pubspec.yaml | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3167c7ef..62d2ddae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,25 +34,24 @@ jobs: - name: Get dependencies run: | - dart pub global activate melos - melos bootstrap + dart run melos bs - name: Generate test data and see if changes run: | - melos gen:actual_data + dart run melos gen:actual_data git --no-pager diff --exit-code packages/core/test_resources/actual_data - name: Run tests for Dart packages if: startsWith(matrix.os, 'ubuntu') - run: melos test:dart --no-select + run: dart run melos test:dart --no-select - name: Run tests for Flutter packages if: startsWith(matrix.os, 'ubuntu') - run: melos test:flutter --no-select + run: dart run melos test:flutter --no-select - name: Run coverage if: startsWith(matrix.os, 'ubuntu') - run: melos coverage + run: dart run melos coverage - uses: codecov/codecov-action@v5 with: @@ -61,10 +60,10 @@ jobs: - name: Generate example then check formats and changes run: | - melos run gen:examples:command --no-select - melos run gen:examples:build_runner --no-select + dart run melos run gen:examples:command --no-select + dart run melos run gen:examples:build_runner --no-select dart format --set-exit-if-changed examples git --no-pager diff --exit-code examples - name: Statically analyze the code - run: melos analyze + run: dart run melos analyze diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index bafd27cc..dd8f0ea8 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -18,6 +18,6 @@ jobs: - name: Install dependencies run: dart pub get - name: Prepare Melos workspace - uses: bluefireteam/melos-action@v3 + run: dart run melos bs - name: Publish - run: melos run publish:force --no-select + run: dart run melos publish:force --no-select diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9e36bff9..400e9079 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,8 +41,7 @@ jobs: - name: Get dependencies run: | - dart pub global activate melos - melos bootstrap + dart run melos bs - name: Running build run: | diff --git a/melos.yaml b/melos.yaml index 302ce455..b2cacc6c 100644 --- a/melos.yaml +++ b/melos.yaml @@ -1,9 +1,11 @@ name: FlutterGen packages: - - packages/** - - integrations/** - - examples/** + - packages/command + - packages/core + - packages/runner + - examples/example + - examples/example_resources ide: intellij: diff --git a/packages/core/test_resources/integration_versions_rive_014/pubspec.yaml b/packages/core/test_resources/integration_versions_rive_014/pubspec.yaml index 7bd8c58d..5c19213b 100644 --- a/packages/core/test_resources/integration_versions_rive_014/pubspec.yaml +++ b/packages/core/test_resources/integration_versions_rive_014/pubspec.yaml @@ -5,7 +5,7 @@ environment: dependencies: rive: ^0.14.0 - flutter_svg: ">=2.0.0 <3.0.0" + flutter_svg: '>=2.0.0 <3.0.0' flutter_gen: output: lib/gen/ From 3eff160f38a46bb29e1ecd3757f3ab50fdad77c0 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Wed, 4 Mar 2026 10:38:16 +0800 Subject: [PATCH 12/19] Fix Melos --- melos.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/melos.yaml b/melos.yaml index b2cacc6c..cc6f8e6c 100644 --- a/melos.yaml +++ b/melos.yaml @@ -75,8 +75,8 @@ scripts: test: run: | - melos test:dart --no-select - melos test:flutter --no-select + dart run melos test:dart --no-select + dart run melos test:flutter --no-select description: dart & flutter test test:dart: From 90b360b77a51fd020d4b51fee5ee73033a0bc6d4 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Wed, 4 Mar 2026 10:44:47 +0800 Subject: [PATCH 13/19] Fix generate --- packages/core/lib/settings/config.dart | 4 ++++ packages/core/scripts/generate_facts.dart | 5 ++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/core/lib/settings/config.dart b/packages/core/lib/settings/config.dart index 682787c0..655b8e18 100644 --- a/packages/core/lib/settings/config.dart +++ b/packages/core/lib/settings/config.dart @@ -10,6 +10,8 @@ import 'package:flutter_gen_core/utils/error.dart'; import 'package:flutter_gen_core/utils/log.dart'; import 'package:flutter_gen_core/utils/map.dart'; import 'package:flutter_gen_core/version.gen.dart'; +import 'package:json_annotation/json_annotation.dart' + show CheckedFromJsonException; import 'package:path/path.dart'; import 'package:pub_semver/pub_semver.dart' show VersionConstraint, Version; import 'package:yaml/yaml.dart'; @@ -165,6 +167,8 @@ Config? loadPubspecConfigOrNull(File pubspecFile, {File? buildFile}) { log.severe('File system error when reading files.', e, s); } on InvalidSettingsException catch (e, s) { log.severe('Invalid settings in files.', e, s); + } on CheckedFromJsonException catch (e, s) { + log.severe('Invalid settings in files.', e, s); } return null; } diff --git a/packages/core/scripts/generate_facts.dart b/packages/core/scripts/generate_facts.dart index 9c7dbf38..02dfc545 100644 --- a/packages/core/scripts/generate_facts.dart +++ b/packages/core/scripts/generate_facts.dart @@ -8,9 +8,8 @@ late final Directory dir; void main() async { dir = File.fromUri(Platform.script).parent.parent.directory('test_resources'); - final configFiles = dir.listSync().whereType().where( - (e) => e.extension == '.yaml', - ); + final configFiles = + dir.listSync().whereType().where((e) => e.extension == '.yaml'); for (final file in configFiles) { final File pubspecFile; final File? buildFile; From b235066694101570f9d4a11034480a2c3f792c99 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Wed, 4 Mar 2026 10:53:10 +0800 Subject: [PATCH 14/19] Fix Melos --- .github/workflows/build.yml | 19 +++++++++---------- .github/workflows/publish.yml | 6 +++--- .github/workflows/release.yml | 5 ++--- melos.yaml | 10 +++++----- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 62d2ddae..013d2942 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,26 +32,25 @@ jobs: if: startsWith(matrix.os, 'windows') run: echo "%LOCALAPPDATA%\Pub\Cache\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - name: Get dependencies - run: | - dart run melos bs + - name: Prepare workspace + uses: bluefireteam/melos-action@v3 - name: Generate test data and see if changes run: | - dart run melos gen:actual_data + melos gen:actual_data git --no-pager diff --exit-code packages/core/test_resources/actual_data - name: Run tests for Dart packages if: startsWith(matrix.os, 'ubuntu') - run: dart run melos test:dart --no-select + run: melos test:dart --no-select - name: Run tests for Flutter packages if: startsWith(matrix.os, 'ubuntu') - run: dart run melos test:flutter --no-select + run: melos test:flutter --no-select - name: Run coverage if: startsWith(matrix.os, 'ubuntu') - run: dart run melos coverage + run: melos coverage - uses: codecov/codecov-action@v5 with: @@ -60,10 +59,10 @@ jobs: - name: Generate example then check formats and changes run: | - dart run melos run gen:examples:command --no-select - dart run melos run gen:examples:build_runner --no-select + melos run gen:examples:command --no-select + melos run gen:examples:build_runner --no-select dart format --set-exit-if-changed examples git --no-pager diff --exit-code examples - name: Statically analyze the code - run: dart run melos analyze + run: melos analyze diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index dd8f0ea8..00a4948b 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -17,7 +17,7 @@ jobs: - uses: flutter-actions/setup-flutter@v4.0 - name: Install dependencies run: dart pub get - - name: Prepare Melos workspace - run: dart run melos bs + - name: Prepare workspace + uses: bluefireteam/melos-action@v3 - name: Publish - run: dart run melos publish:force --no-select + run: melos publish:force --no-select diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 400e9079..4f3bab04 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -39,9 +39,8 @@ jobs: - name: Set environment run: echo "$HOME/.pub-cache/bin" >> $GITHUB_PATH - - name: Get dependencies - run: | - dart run melos bs + - name: Prepare workspace + uses: bluefireteam/melos-action@v3 - name: Running build run: | diff --git a/melos.yaml b/melos.yaml index cc6f8e6c..caf2d912 100644 --- a/melos.yaml +++ b/melos.yaml @@ -43,7 +43,7 @@ scripts: description: flutter build apk gen:build_runner: - exec: dart run build_runner build --delete-conflicting-outputs + exec: dart run build_runner build -d packageFilters: ignore: - example @@ -60,14 +60,14 @@ scripts: description: dart ../../packages/command/bin/flutter_gen_command.dart gen:examples:build_runner: - run: flutter pub run build_runner build --delete-conflicting-outputs + run: dart run build_runner build -d exec: concurrency: 1 packageFilters: scope: - example - example_resources - description: flutter pub run build_runner build --delete-conflicting-outputs + description: dart run build_runner build --delete-conflicting-outputs gen:actual_data: run: dart packages/core/scripts/generate_facts.dart @@ -75,8 +75,8 @@ scripts: test: run: | - dart run melos test:dart --no-select - dart run melos test:flutter --no-select + melos test:dart --no-select + melos test:flutter --no-select description: dart & flutter test test:dart: From d67280a287e092b5420c27944eac7fa78d3aa942 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Wed, 4 Mar 2026 10:53:23 +0800 Subject: [PATCH 15/19] Fix formats --- .../test/assets_gen_integrations_test.dart | 38 +++++++++++-------- packages/core/test/config_test.dart | 4 +- packages/core/test/settings_test.dart | 32 ++++++++-------- 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/packages/core/test/assets_gen_integrations_test.dart b/packages/core/test/assets_gen_integrations_test.dart index e96b7bf2..b24a567f 100644 --- a/packages/core/test/assets_gen_integrations_test.dart +++ b/packages/core/test/assets_gen_integrations_test.dart @@ -317,14 +317,20 @@ void main() { resolvedVersionConstraint: VersionConstraint.parse('^0.14.0'), ); expect(fallbackIntegration, isA()); - expect(fallbackIntegration.classOutput.contains('riveFileLoader({'), isTrue); + expect( + fallbackIntegration.classOutput.contains('riveFileLoader({'), + isTrue, + ); }); test('RiveIntegration fallback behavior', () { // Test with no version information (should return RiveIntegration0140 as fallback) final fallbackIntegration = RiveIntegration(''); expect(fallbackIntegration, isA()); - expect(fallbackIntegration.classOutput.contains('riveFileLoader({'), isTrue); + expect( + fallbackIntegration.classOutput.contains('riveFileLoader({'), + isTrue, + ); }); test('RiveIntegrationClassic classOutput structure', () { @@ -359,7 +365,7 @@ void main() { isTrue, ); expect( - output.contains("'packages/test_package/\$_assetName'"), + output.contains(r"'packages/test_package/$_assetName'"), isTrue, ); }); @@ -376,7 +382,10 @@ void main() { expect(output.contains('_rive.FileLoader riveFileLoader({'), isTrue); expect(output.contains('_rive.FileLoader.fromAsset'), isTrue); expect(output.contains('_rive.Factory? factory,'), isTrue); - expect(output.contains('riveFactory: factory ?? _rive.Factory.rive'), isTrue); + expect( + output.contains('riveFactory: factory ?? _rive.Factory.rive'), + isTrue, + ); expect(output.contains('String get path =>'), isTrue); expect(output.contains('String get keyName =>'), isTrue); @@ -398,7 +407,7 @@ void main() { isTrue, ); expect( - output.contains("'packages/test_package/\$_assetName'"), + output.contains(r"'packages/test_package/$_assetName'"), isTrue, ); }); @@ -462,11 +471,10 @@ void main() { test('Integration version resolution in AssetsGenConfig', () { // Test that version resolution is properly integrated into assets generation - // This validates the full flow from config loading to integration creation - + // This validates the full flow from config loading to integration creation. // Create a RiveIntegration with both resolved version and constraint // When resolvedVersion is 0.13.0 (< 0.14.0), it should use Classic - // even if resolvedVersionConstraint would allow 0.14.0 + // even if resolvedVersionConstraint would allow 0.14.0. final integrationWithBoth = RiveIntegration( '', resolvedVersion: Version(0, 13, 0), @@ -474,14 +482,14 @@ void main() { ); // resolvedVersion takes priority: 0.13.0 < 0.14.0 => Classic expect(integrationWithBoth, isA()); - + // Create a RiveIntegration with only resolvedVersion final integrationVersionOnly = RiveIntegration( '', resolvedVersion: Version(0, 14, 0), ); expect(integrationVersionOnly, isA()); - + // Create a RiveIntegration with only resolvedVersionConstraint final integrationConstraintOnly = RiveIntegration( '', @@ -497,35 +505,35 @@ void main() { resolvedVersionConstraint: VersionConstraint.parse('^0.13.5'), ); expect(caretOld, isA()); - + // Test with ^0.14.x constraint (should use 0140) final caretNew = RiveIntegration( '', resolvedVersionConstraint: VersionConstraint.parse('^0.14.1'), ); expect(caretNew, isA()); - + // Test with >= constraint that includes 0.14.0 final rangeIncludesNew = RiveIntegration( '', resolvedVersionConstraint: VersionConstraint.parse('>=0.13.0 <1.0.0'), ); expect(rangeIncludesNew, isA()); - + // Test with >= constraint that excludes 0.14.0 final rangeExcludesNew = RiveIntegration( '', resolvedVersionConstraint: VersionConstraint.parse('>=0.13.0 <0.14.0'), ); expect(rangeExcludesNew, isA()); - + // Test with exact version < 0.14.0 final exactOld = RiveIntegration( '', resolvedVersion: Version(0, 13, 99), ); expect(exactOld, isA()); - + // Test with exact version >= 0.14.0 final exactNew = RiveIntegration( '', diff --git a/packages/core/test/config_test.dart b/packages/core/test/config_test.dart index 7f4baabb..fb375f1d 100644 --- a/packages/core/test/config_test.dart +++ b/packages/core/test/config_test.dart @@ -101,7 +101,7 @@ void main() { // Verify that only integration types from the registry are in the maps final expectedTypes = integrationPackages.keys.toList(); - + for (final key in config.integrationVersionConstraints.keys) { expect( expectedTypes.contains(key), @@ -109,7 +109,7 @@ void main() { reason: 'Unexpected integration type: $key', ); } - + for (final key in config.integrationResolvedVersions.keys) { expect( expectedTypes.contains(key), diff --git a/packages/core/test/settings_test.dart b/packages/core/test/settings_test.dart index b2a32b2c..c6c0c7d8 100644 --- a/packages/core/test/settings_test.dart +++ b/packages/core/test/settings_test.dart @@ -136,19 +136,19 @@ flutter: - assets/ '''); final pubspec = Pubspec.fromJson(yaml); - + expect(pubspec.dependenciesVersionConstraint['rive'], isNotNull); expect( pubspec.dependenciesVersionConstraint['rive'], equals(VersionConstraint.parse('^0.13.0')), ); - + expect(pubspec.dependenciesVersionConstraint['flutter_svg'], isNotNull); expect( pubspec.dependenciesVersionConstraint['flutter_svg'], equals(VersionConstraint.parse('^2.0.0')), ); - + expect(pubspec.dependenciesVersionConstraint['lottie'], isNotNull); expect( pubspec.dependenciesVersionConstraint['lottie'], @@ -173,13 +173,13 @@ flutter: - assets/ '''); final pubspec = Pubspec.fromJson(yaml); - + expect(pubspec.dependenciesVersionConstraint['rive'], isNotNull); expect( pubspec.dependenciesVersionConstraint['rive'], equals(VersionConstraint.parse('^0.14.0')), ); - + expect(pubspec.dependenciesVersionConstraint['flutter_svg'], isNotNull); expect( pubspec.dependenciesVersionConstraint['flutter_svg'], @@ -203,10 +203,10 @@ flutter: - assets/ '''); final pubspec = Pubspec.fromJson(yaml); - + // Path dependency should be null since no version constraint expect(pubspec.dependenciesVersionConstraint['rive'], isNull); - + // String version should still work expect(pubspec.dependenciesVersionConstraint['flutter_svg'], isNotNull); expect( @@ -233,10 +233,10 @@ flutter: - assets/ '''); final pubspec = Pubspec.fromJson(yaml); - + // Git dependency should be null since no version constraint expect(pubspec.dependenciesVersionConstraint['rive'], isNull); - + // String version should still work expect(pubspec.dependenciesVersionConstraint['lottie'], isNotNull); expect( @@ -260,15 +260,15 @@ flutter: - assets/ '''); final pubspec = Pubspec.fromJson(yaml); - + // Invalid version should be null expect(pubspec.dependenciesVersionConstraint['rive'], isNull); - + // Valid version should work expect(pubspec.dependenciesVersionConstraint['flutter_svg'], isNotNull); }); - test('handles dependencies with version key containing invalid version', () { + test('handles dependencies with invalid version', () { final yaml = loadYaml(''' name: test environment: @@ -284,10 +284,10 @@ flutter: - assets/ '''); final pubspec = Pubspec.fromJson(yaml); - + // Invalid version in map should be null expect(pubspec.dependenciesVersionConstraint['rive'], isNull); - + // Valid string version should work expect(pubspec.dependenciesVersionConstraint['lottie'], isNotNull); }); @@ -304,7 +304,7 @@ flutter: - assets/ '''); final pubspec = Pubspec.fromJson(yaml); - + // Should return empty map for null dependencies expect(pubspec.dependenciesVersionConstraint, isEmpty); }); @@ -330,7 +330,7 @@ flutter: - assets/ '''); final pubspec = Pubspec.fromJson(yaml); - + expect( pubspec.dependenciesVersionConstraint['rive'], equals(VersionConstraint.parse('^0.13.0')), From 8573a44ae9c0123ef11c79615bd2a9c9ac7374b9 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Wed, 4 Mar 2026 11:42:00 +0800 Subject: [PATCH 16/19] Improve integration constraints --- .../integrations/rive_integration.dart | 61 +++++++++++-------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/packages/core/lib/generators/integrations/rive_integration.dart b/packages/core/lib/generators/integrations/rive_integration.dart index 9a8ff6af..fde44462 100644 --- a/packages/core/lib/generators/integrations/rive_integration.dart +++ b/packages/core/lib/generators/integrations/rive_integration.dart @@ -1,10 +1,9 @@ import 'package:flutter_gen_core/generators/integrations/integration.dart'; -import 'package:pub_semver/pub_semver.dart' show Version, VersionConstraint; - -typedef RiveIntegrationLatest = RiveIntegration0140; +import 'package:pub_semver/pub_semver.dart' + show Version, VersionConstraint, VersionRange; /// Create Rive integration based on the resolved version. -abstract final class RiveIntegration extends Integration { +sealed class RiveIntegration extends Integration { factory RiveIntegration( String packageName, { Version? resolvedVersion, @@ -12,32 +11,39 @@ abstract final class RiveIntegration extends Integration { }) { // Resolve integration by version. RiveIntegration? integration = switch (resolvedVersion) { - final v? when v < Version(0, 14, 0) => + final v? when v < RiveIntegration0140.minimumSupportVersion => RiveIntegrationClassic(packageName), - Version() => RiveIntegrationLatest(packageName), + Version() => RiveIntegration0140(packageName), null => null, }; // Resolve integration by version constraint. integration ??= switch (resolvedVersionConstraint) { - final c? when c.allows(Version(0, 14, 0)) => - RiveIntegrationLatest(packageName), + final VersionRange c => switch (c.max) { + final max? when max == RiveIntegration0140.minimumSupportVersion => + c.includeMax + ? RiveIntegration0140(packageName) + : RiveIntegrationClassic(packageName), + final max? when max > RiveIntegration0140.minimumSupportVersion => + RiveIntegration0140(packageName), + _ => RiveIntegrationClassic(packageName), + }, VersionConstraint() => RiveIntegrationClassic(packageName), null => null, }; // Use the latest integration as the fallback. - integration ??= RiveIntegrationLatest(packageName); + integration ??= RiveIntegration0140(packageName); return integration; } RiveIntegration._(String packageName) : super(packageName); -} -/// Rive integration for versions before 0.14.0. -final class RiveIntegrationClassic extends RiveIntegration { - RiveIntegrationClassic(String packageName) : super._(packageName); + String get _classDefinition; + + @override + String get classOutput => _classDefinition; String? get packageExpression => isPackage ? 'packages/$packageName/' : null; @@ -48,8 +54,20 @@ final class RiveIntegrationClassic extends RiveIntegration { ]; @override - String get classOutput => _classDefinition; + String get className => 'RiveGenImage'; + + @override + bool isSupport(AssetType asset) => asset.extension == '.riv'; + + @override + bool get isConstConstructor => true; +} + +/// Rive integration for versions before 0.14.0. +final class RiveIntegrationClassic extends RiveIntegration { + RiveIntegrationClassic(String packageName) : super._(packageName); + @override String get _classDefinition => '''class RiveGenImage { const RiveGenImage( this._assetName, { @@ -92,20 +110,13 @@ ${isPackage ? "\n static const String package = '$packageName';" : ''} String get keyName => ${isPackage ? '\'$packageExpression\$_assetName\'' : '_assetName'}; }'''; - - @override - String get className => 'RiveGenImage'; - - @override - bool isSupport(AssetType asset) => asset.extension == '.riv'; - - @override - bool get isConstConstructor => true; } /// Rive integration for versions equal to or above 0.14.0. -final class RiveIntegration0140 extends RiveIntegrationClassic { - RiveIntegration0140(String packageName) : super(packageName); +final class RiveIntegration0140 extends RiveIntegration { + RiveIntegration0140(String packageName) : super._(packageName); + + static final minimumSupportVersion = Version(0, 14, 0, pre: '0'); @override String get _classDefinition => '''class RiveGenImage { From 57483209a941e245741e82f243e50384bd7fcc84 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Wed, 4 Mar 2026 11:42:41 +0800 Subject: [PATCH 17/19] Fix tests --- packages/core/test/flutter_gen_test.dart | 13 ++++++----- packages/core/test/settings_test.dart | 28 +++++++++++++++++------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/packages/core/test/flutter_gen_test.dart b/packages/core/test/flutter_gen_test.dart index e28b3e0d..c3814a26 100644 --- a/packages/core/test/flutter_gen_test.dart +++ b/packages/core/test/flutter_gen_test.dart @@ -172,11 +172,14 @@ void main() { test('Wrong lineLength', () async { const pubspec = 'test_resources/pubspec_wrong_line_length.yaml'; - - expect( - () => FlutterGenerator(File(pubspec)).build(), - throwsA(isA()), - ); + const assets = 'pubspec_wrong_line_length_assets.gen.dart'; + const colors = 'pubspec_wrong_line_length_colors.gen.dart'; + const fonts = 'pubspec_wrong_line_length_fonts.gen.dart'; + + await FlutterGenerator(File(pubspec)).build(); + expect(File('test_resources/lib/gen/$assets').existsSync(), false); + expect(File('test_resources/lib/gen/$fonts').existsSync(), false); + expect(File('test_resources/lib/gen/$colors').existsSync(), false); }); test('Disabled generation', () async { diff --git a/packages/core/test/settings_test.dart b/packages/core/test/settings_test.dart index c6c0c7d8..0d5b6cf3 100644 --- a/packages/core/test/settings_test.dart +++ b/packages/core/test/settings_test.dart @@ -1,9 +1,12 @@ import 'package:collection/collection.dart'; import 'package:flutter_gen_core/settings/asset_type.dart'; +import 'package:flutter_gen_core/settings/config_default.dart' + show configDefaultYamlContent; import 'package:flutter_gen_core/settings/flavored_asset.dart'; import 'package:flutter_gen_core/settings/pubspec.dart'; import 'package:flutter_gen_core/utils/error.dart' show InvalidSettingsException; +import 'package:flutter_gen_core/utils/map.dart' show mergeMap; import 'package:pub_semver/pub_semver.dart'; import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; @@ -120,8 +123,9 @@ void main() { }); group('Pubspec.dependenciesVersionConstraint', () { + final defaultMap = loadYaml(configDefaultYamlContent) as YamlMap?; test('parses string version constraints', () { - final yaml = loadYaml(''' + Map yaml = loadYaml(''' name: test environment: sdk: ^3.0.0 @@ -135,6 +139,7 @@ flutter: assets: - assets/ '''); + yaml = mergeMap([defaultMap, yaml]); final pubspec = Pubspec.fromJson(yaml); expect(pubspec.dependenciesVersionConstraint['rive'], isNotNull); @@ -157,7 +162,7 @@ flutter: }); test('parses map with version key', () { - final yaml = loadYaml(''' + Map yaml = loadYaml(''' name: test environment: sdk: ^3.0.0 @@ -172,6 +177,7 @@ flutter: assets: - assets/ '''); + yaml = mergeMap([defaultMap, yaml]); final pubspec = Pubspec.fromJson(yaml); expect(pubspec.dependenciesVersionConstraint['rive'], isNotNull); @@ -188,7 +194,7 @@ flutter: }); test('handles path dependencies without version', () { - final yaml = loadYaml(''' + Map yaml = loadYaml(''' name: test environment: sdk: ^3.0.0 @@ -202,6 +208,7 @@ flutter: assets: - assets/ '''); + yaml = mergeMap([defaultMap, yaml]); final pubspec = Pubspec.fromJson(yaml); // Path dependency should be null since no version constraint @@ -216,7 +223,7 @@ flutter: }); test('handles git dependencies without version', () { - final yaml = loadYaml(''' + Map yaml = loadYaml(''' name: test environment: sdk: ^3.0.0 @@ -232,6 +239,7 @@ flutter: assets: - assets/ '''); + yaml = mergeMap([defaultMap, yaml]); final pubspec = Pubspec.fromJson(yaml); // Git dependency should be null since no version constraint @@ -246,7 +254,7 @@ flutter: }); test('handles invalid version strings gracefully', () { - final yaml = loadYaml(''' + Map yaml = loadYaml(''' name: test environment: sdk: ^3.0.0 @@ -259,6 +267,7 @@ flutter: assets: - assets/ '''); + yaml = mergeMap([defaultMap, yaml]); final pubspec = Pubspec.fromJson(yaml); // Invalid version should be null @@ -269,7 +278,7 @@ flutter: }); test('handles dependencies with invalid version', () { - final yaml = loadYaml(''' + Map yaml = loadYaml(''' name: test environment: sdk: ^3.0.0 @@ -283,6 +292,7 @@ flutter: assets: - assets/ '''); + yaml = mergeMap([defaultMap, yaml]); final pubspec = Pubspec.fromJson(yaml); // Invalid version in map should be null @@ -293,7 +303,7 @@ flutter: }); test('handles null dependencies', () { - final yaml = loadYaml(''' + Map yaml = loadYaml(''' name: test environment: sdk: ^3.0.0 @@ -303,6 +313,7 @@ flutter: assets: - assets/ '''); + yaml = mergeMap([defaultMap, yaml]); final pubspec = Pubspec.fromJson(yaml); // Should return empty map for null dependencies @@ -310,7 +321,7 @@ flutter: }); test('handles mixed dependency formats', () { - final yaml = loadYaml(''' + Map yaml = loadYaml(''' name: test environment: sdk: ^3.0.0 @@ -329,6 +340,7 @@ flutter: assets: - assets/ '''); + yaml = mergeMap([defaultMap, yaml]); final pubspec = Pubspec.fromJson(yaml); expect( From 126541bb8a53cb4203eae0581119e473eae8ee7f Mon Sep 17 00:00:00 2001 From: Alex Li Date: Wed, 4 Mar 2026 11:53:50 +0800 Subject: [PATCH 18/19] Update tests --- packages/core/test/assets_gen_integrations_test.dart | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/core/test/assets_gen_integrations_test.dart b/packages/core/test/assets_gen_integrations_test.dart index b24a567f..55cb5df1 100644 --- a/packages/core/test/assets_gen_integrations_test.dart +++ b/packages/core/test/assets_gen_integrations_test.dart @@ -514,11 +514,18 @@ void main() { expect(caretNew, isA()); // Test with >= constraint that includes 0.14.0 - final rangeIncludesNew = RiveIntegration( + final rangeIncludesNew1 = RiveIntegration( '', resolvedVersionConstraint: VersionConstraint.parse('>=0.13.0 <1.0.0'), ); - expect(rangeIncludesNew, isA()); + expect(rangeIncludesNew1, isA()); + + // Test with >= constraint that allows 0.14.0. + final rangeIncludesNew2 = RiveIntegration( + '', + resolvedVersionConstraint: VersionConstraint.parse('>=0.13.0 <=0.14.0'), + ); + expect(rangeIncludesNew2, isA()); // Test with >= constraint that excludes 0.14.0 final rangeExcludesNew = RiveIntegration( From 31cca2c308d496dd82bc35da092468c6d468ddfe Mon Sep 17 00:00:00 2001 From: Alex Li Date: Wed, 4 Mar 2026 12:01:06 +0800 Subject: [PATCH 19/19] Update tests --- .../core/test/assets_gen_integrations_test.dart | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/core/test/assets_gen_integrations_test.dart b/packages/core/test/assets_gen_integrations_test.dart index 55cb5df1..e07560f3 100644 --- a/packages/core/test/assets_gen_integrations_test.dart +++ b/packages/core/test/assets_gen_integrations_test.dart @@ -514,18 +514,19 @@ void main() { expect(caretNew, isA()); // Test with >= constraint that includes 0.14.0 - final rangeIncludesNew1 = RiveIntegration( + final rangeIncludesNew = RiveIntegration( '', resolvedVersionConstraint: VersionConstraint.parse('>=0.13.0 <1.0.0'), ); - expect(rangeIncludesNew1, isA()); + expect(rangeIncludesNew, isA()); - // Test with >= constraint that allows 0.14.0. - final rangeIncludesNew2 = RiveIntegration( + // Test with >= constraint that includes the minimum pre-release. + final rangeIncludesPre = RiveIntegration( '', - resolvedVersionConstraint: VersionConstraint.parse('>=0.13.0 <=0.14.0'), + resolvedVersionConstraint: + VersionConstraint.parse('>=0.13.0 <=0.14.0-0'), ); - expect(rangeIncludesNew2, isA()); + expect(rangeIncludesPre, isA()); // Test with >= constraint that excludes 0.14.0 final rangeExcludesNew = RiveIntegration(