diff --git a/Makefile b/Makefile index 2b995ab..029a986 100644 --- a/Makefile +++ b/Makefile @@ -28,14 +28,19 @@ build_ios: install ## Run the iOS build of the example app (located inside `widg build_android: install ## Run the Android build of the example app (located inside `widget_driver/example`) without deploying to any device bash scripts/run-android-build.sh +build_macos: install ## Run the macOS build of the example app (located inside `widget_driver/example`) without deploying to any device + bash scripts/run-macos-build.sh + +build_web: install ## Run the web build of the example app (located inside `widget_driver/example`) without deploying to any device + bash scripts/run-web-build.sh watch: install ## Starts the example app and performs the hot reload in case of any change bash scripts/run-and-watch.sh quality: clean install lint test ## Run only linter and tests -build: install build_ios build_android ## Build the example Android and iOS apps from the widget_driver package +build: install build_ios build_android build_macos build_web ## Build the example Android, iOS, macOS, and web apps from the widget_driver package -all: clean install lint test build_ios build_android ## Run all steps including building the Android and iOS +all: clean install lint test build_ios build_android build_macos build_web ## Run all steps including building the Android, iOS, macOS, and web help: ## Show all commands @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' diff --git a/scripts/run-macos-build.sh b/scripts/run-macos-build.sh new file mode 100644 index 0000000..65fcde9 --- /dev/null +++ b/scripts/run-macos-build.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +TAG="[widget-driver]:" +RED='\033[0;31m' +GREEN='\033[0;32m' +NC='\033[0m' +TAG_COLOR="\n${GREEN}${TAG}${NC}" + +function run_macos_build() { + echo -e "$TAG_COLOR Building macOS Example app" + make install + cd widget_driver/example + flutter build macos --debug --no-tree-shake-icons $1 + echo -e "$TAG_COLOR Example app succesufully built" +} + +run_macos_build $@ diff --git a/scripts/run-web-build.sh b/scripts/run-web-build.sh new file mode 100644 index 0000000..6fc4b05 --- /dev/null +++ b/scripts/run-web-build.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +TAG="[widget-driver]:" +RED='\033[0;31m' +GREEN='\033[0;32m' +NC='\033[0m' +TAG_COLOR="\n${GREEN}${TAG}${NC}" + +function run_web_build() { + echo -e "$TAG_COLOR Building Web Example app" + make install + cd widget_driver/example + flutter build web --debug --no-tree-shake-icons $1 + echo -e "$TAG_COLOR Example app succesufully built" +} + +run_web_build $@ diff --git a/widget_driver/example/lib/pub_dev_example_code/my_first_drivable_widget_driver.g.dart b/widget_driver/example/lib/pub_dev_example_code/my_first_drivable_widget_driver.g.dart index 0a84f4f..f99186e 100644 --- a/widget_driver/example/lib/pub_dev_example_code/my_first_drivable_widget_driver.g.dart +++ b/widget_driver/example/lib/pub_dev_example_code/my_first_drivable_widget_driver.g.dart @@ -8,7 +8,7 @@ part of 'my_first_drivable_widget_driver.dart'; // coverage:ignore-file -// This file was generated with widget_driver_generator version "1.3.6" +// This file was generated with widget_driver_generator version "1.4.0-pre.1" class _$TestMyFirstDrivableWidgetDriver extends TestDriver implements MyFirstDrivableWidgetDriver { @override diff --git a/widget_driver/example/lib/widgets/coffee_community/coffee_community_page_driver.g.dart b/widget_driver/example/lib/widgets/coffee_community/coffee_community_page_driver.g.dart index 770cb39..56dcbe7 100644 --- a/widget_driver/example/lib/widgets/coffee_community/coffee_community_page_driver.g.dart +++ b/widget_driver/example/lib/widgets/coffee_community/coffee_community_page_driver.g.dart @@ -8,7 +8,7 @@ part of 'coffee_community_page_driver.dart'; // coverage:ignore-file -// This file was generated with widget_driver_generator version "1.3.6" +// This file was generated with widget_driver_generator version "1.4.0-pre.1" class _$TestCoffeeCommunityPageDriver extends TestDriver implements CoffeeCommunityPageDriver { @override diff --git a/widget_driver/example/lib/widgets/coffee_community/coffee_library/coffee_detail/coffee_detail_page_driver.g.dart b/widget_driver/example/lib/widgets/coffee_community/coffee_library/coffee_detail/coffee_detail_page_driver.g.dart index 02c7c20..29e921d 100644 --- a/widget_driver/example/lib/widgets/coffee_community/coffee_library/coffee_detail/coffee_detail_page_driver.g.dart +++ b/widget_driver/example/lib/widgets/coffee_community/coffee_library/coffee_detail/coffee_detail_page_driver.g.dart @@ -8,7 +8,7 @@ part of 'coffee_detail_page_driver.dart'; // coverage:ignore-file -// This file was generated with widget_driver_generator version "1.3.6" +// This file was generated with widget_driver_generator version "1.4.0-pre.1" class _$TestCoffeeDetailPageDriver extends TestDriver implements CoffeeDetailPageDriver { @override diff --git a/widget_driver/example/lib/widgets/coffee_community/coffee_library/coffee_library_page_driver.dart b/widget_driver/example/lib/widgets/coffee_community/coffee_library/coffee_library_page_driver.dart index a17475f..38fc0e8 100644 --- a/widget_driver/example/lib/widgets/coffee_community/coffee_library/coffee_library_page_driver.dart +++ b/widget_driver/example/lib/widgets/coffee_community/coffee_library/coffee_library_page_driver.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:example/models/coffee.dart' as c; +import 'package:example/models/coffee.dart' as b; import 'package:get_it/get_it.dart'; import 'package:widget_driver/widget_driver.dart'; @@ -12,7 +12,7 @@ part 'coffee_library_page_driver.g.dart'; class CoffeeLibraryPageDriver extends WidgetDriver { final CoffeeService _coffeeService; bool _isFetching = false; - List _coffees = []; + List _coffees = []; StreamSubscription? _subscription; CoffeeLibraryPageDriver({ @@ -30,7 +30,7 @@ class CoffeeLibraryPageDriver extends WidgetDriver { int get numberOfCoffees => _coffees.length; - c.Coffee getCoffeeAtIndex(int index) { + b.Coffee getCoffeeAtIndex(int index) { return _coffees[index]; } diff --git a/widget_driver/example/lib/widgets/coffee_community/coffee_library/coffee_library_page_driver.g.dart b/widget_driver/example/lib/widgets/coffee_community/coffee_library/coffee_library_page_driver.g.dart index b2dc5c9..e2d1967 100644 --- a/widget_driver/example/lib/widgets/coffee_community/coffee_library/coffee_library_page_driver.g.dart +++ b/widget_driver/example/lib/widgets/coffee_community/coffee_library/coffee_library_page_driver.g.dart @@ -8,7 +8,7 @@ part of 'coffee_library_page_driver.dart'; // coverage:ignore-file -// This file was generated with widget_driver_generator version "1.3.6" +// This file was generated with widget_driver_generator version "1.4.0-pre.1" class _$TestCoffeeLibraryPageDriver extends TestDriver implements CoffeeLibraryPageDriver { @override @@ -18,8 +18,8 @@ class _$TestCoffeeLibraryPageDriver extends TestDriver implements CoffeeLibraryP int get numberOfCoffees => 123; @override - c.Coffee getCoffeeAtIndex(int index) { - return const c.Coffee( + b.Coffee getCoffeeAtIndex(int index) { + return const b.Coffee( name: 'Coffee', description: 'Some desc', imageUrl: 'http://www.exampleImage.com/image', diff --git a/widget_driver/example/lib/widgets/coffee_community/not_logged_in/not_logged_in_page_driver.g.dart b/widget_driver/example/lib/widgets/coffee_community/not_logged_in/not_logged_in_page_driver.g.dart index 4d50984..2e33d25 100644 --- a/widget_driver/example/lib/widgets/coffee_community/not_logged_in/not_logged_in_page_driver.g.dart +++ b/widget_driver/example/lib/widgets/coffee_community/not_logged_in/not_logged_in_page_driver.g.dart @@ -8,7 +8,7 @@ part of 'not_logged_in_page_driver.dart'; // coverage:ignore-file -// This file was generated with widget_driver_generator version "1.3.6" +// This file was generated with widget_driver_generator version "1.4.0-pre.1" class _$TestNotLoggedInPageDriver extends TestDriver implements NotLoggedInPageDriver { @override diff --git a/widget_driver/example/lib/widgets/coffee_community/not_logged_in/register_account/register_account_page_driver.dart b/widget_driver/example/lib/widgets/coffee_community/not_logged_in/register_account/register_account_page_driver.dart index b810ad6..cb6e879 100644 --- a/widget_driver/example/lib/widgets/coffee_community/not_logged_in/register_account/register_account_page_driver.dart +++ b/widget_driver/example/lib/widgets/coffee_community/not_logged_in/register_account/register_account_page_driver.dart @@ -47,7 +47,9 @@ class RegisterAccountPageDriver extends WidgetDriver { _setRegisterLoading(true); await _createUserService.createUserAndLogin(_currentUsername); _setRegisterLoading(false); - _coordinator.pop(context: context); + if (context.mounted) { + _coordinator.pop(context: context); + } } else { _validateUsernameInput(); } diff --git a/widget_driver/example/lib/widgets/coffee_community/not_logged_in/register_account/register_account_page_driver.g.dart b/widget_driver/example/lib/widgets/coffee_community/not_logged_in/register_account/register_account_page_driver.g.dart index cfa92da..efec289 100644 --- a/widget_driver/example/lib/widgets/coffee_community/not_logged_in/register_account/register_account_page_driver.g.dart +++ b/widget_driver/example/lib/widgets/coffee_community/not_logged_in/register_account/register_account_page_driver.g.dart @@ -8,7 +8,7 @@ part of 'register_account_page_driver.dart'; // coverage:ignore-file -// This file was generated with widget_driver_generator version "1.3.6" +// This file was generated with widget_driver_generator version "1.4.0-pre.1" class _$TestRegisterAccountPageDriver extends TestDriver implements RegisterAccountPageDriver { @override diff --git a/widget_driver/example/lib/widgets/coffee_consumption/coffee_counter/coffee_counter_header_section_driver.g.dart b/widget_driver/example/lib/widgets/coffee_consumption/coffee_counter/coffee_counter_header_section_driver.g.dart index a6e9c66..7a53e94 100644 --- a/widget_driver/example/lib/widgets/coffee_consumption/coffee_counter/coffee_counter_header_section_driver.g.dart +++ b/widget_driver/example/lib/widgets/coffee_consumption/coffee_counter/coffee_counter_header_section_driver.g.dart @@ -8,7 +8,7 @@ part of 'coffee_counter_header_section_driver.dart'; // coverage:ignore-file -// This file was generated with widget_driver_generator version "1.3.6" +// This file was generated with widget_driver_generator version "1.4.0-pre.1" class _$TestCoffeeCounterHeaderSectionDriver extends TestDriver implements CoffeeCounterHeaderSectionDriver { @override diff --git a/widget_driver/example/lib/widgets/coffee_consumption/coffee_counter/coffee_counter_widget_driver.g.dart b/widget_driver/example/lib/widgets/coffee_consumption/coffee_counter/coffee_counter_widget_driver.g.dart index edd5d92..5cf35bf 100644 --- a/widget_driver/example/lib/widgets/coffee_consumption/coffee_counter/coffee_counter_widget_driver.g.dart +++ b/widget_driver/example/lib/widgets/coffee_consumption/coffee_counter/coffee_counter_widget_driver.g.dart @@ -8,7 +8,7 @@ part of 'coffee_counter_widget_driver.dart'; // coverage:ignore-file -// This file was generated with widget_driver_generator version "1.3.6" +// This file was generated with widget_driver_generator version "1.4.0-pre.1" class _$TestCoffeeCounterWidgetDriver extends TestDriver implements CoffeeCounterWidgetDriver { @override diff --git a/widget_driver/example/lib/widgets/coffee_consumption/random_coffee_image_widget/random_coffee_image_widget_driver.g.dart b/widget_driver/example/lib/widgets/coffee_consumption/random_coffee_image_widget/random_coffee_image_widget_driver.g.dart index 3be0ece..ccca769 100644 --- a/widget_driver/example/lib/widgets/coffee_consumption/random_coffee_image_widget/random_coffee_image_widget_driver.g.dart +++ b/widget_driver/example/lib/widgets/coffee_consumption/random_coffee_image_widget/random_coffee_image_widget_driver.g.dart @@ -8,7 +8,7 @@ part of 'random_coffee_image_widget_driver.dart'; // coverage:ignore-file -// This file was generated with widget_driver_generator version "1.3.6" +// This file was generated with widget_driver_generator version "1.4.0-pre.1" class _$TestRandomCoffeeImageWidgetDriver extends TestDriver implements RandomCoffeeImageWidgetDriver { @override diff --git a/widget_driver/example/lib/widgets/home_page/home_page_driver.g.dart b/widget_driver/example/lib/widgets/home_page/home_page_driver.g.dart index ca4262d..db17a5a 100644 --- a/widget_driver/example/lib/widgets/home_page/home_page_driver.g.dart +++ b/widget_driver/example/lib/widgets/home_page/home_page_driver.g.dart @@ -8,7 +8,7 @@ part of 'home_page_driver.dart'; // coverage:ignore-file -// This file was generated with widget_driver_generator version "1.3.6" +// This file was generated with widget_driver_generator version "1.4.0-pre.1" class _$TestHomePageDriver extends TestDriver implements HomePageDriver { @override diff --git a/widget_driver/example/lib/widgets/home_page/log_in_out_button/log_in_out_button_driver.g.dart b/widget_driver/example/lib/widgets/home_page/log_in_out_button/log_in_out_button_driver.g.dart index d3c3219..86867c7 100644 --- a/widget_driver/example/lib/widgets/home_page/log_in_out_button/log_in_out_button_driver.g.dart +++ b/widget_driver/example/lib/widgets/home_page/log_in_out_button/log_in_out_button_driver.g.dart @@ -8,7 +8,7 @@ part of 'log_in_out_button_driver.dart'; // coverage:ignore-file -// This file was generated with widget_driver_generator version "1.3.6" +// This file was generated with widget_driver_generator version "1.4.0-pre.1" class _$TestLogInOutButtonDriver extends TestDriver implements LogInOutButtonDriver { @override diff --git a/widget_driver/example/lib/widgets/my_app_driver.g.dart b/widget_driver/example/lib/widgets/my_app_driver.g.dart index 7f9e16f..0d93837 100644 --- a/widget_driver/example/lib/widgets/my_app_driver.g.dart +++ b/widget_driver/example/lib/widgets/my_app_driver.g.dart @@ -8,7 +8,7 @@ part of 'my_app_driver.dart'; // coverage:ignore-file -// This file was generated with widget_driver_generator version "1.3.6" +// This file was generated with widget_driver_generator version "1.4.0-pre.1" class _$TestMyAppDriver extends TestDriver implements MyAppDriver { @override diff --git a/widget_driver/example/lib/widgets/playground/playground_test_widget/playground_test_child_widget_driver.g.dart b/widget_driver/example/lib/widgets/playground/playground_test_widget/playground_test_child_widget_driver.g.dart index 093a34d..987f872 100644 --- a/widget_driver/example/lib/widgets/playground/playground_test_widget/playground_test_child_widget_driver.g.dart +++ b/widget_driver/example/lib/widgets/playground/playground_test_widget/playground_test_child_widget_driver.g.dart @@ -8,7 +8,7 @@ part of 'playground_test_child_widget_driver.dart'; // coverage:ignore-file -// This file was generated with widget_driver_generator version "1.3.6" +// This file was generated with widget_driver_generator version "1.4.0-pre.1" class _$TestPlaygroundTestChildWidgetDriver extends TestDriver implements PlaygroundTestChildWidgetDriver { @override diff --git a/widget_driver/example/lib/widgets/playground/playground_test_widget/playground_test_widget_driver.g.dart b/widget_driver/example/lib/widgets/playground/playground_test_widget/playground_test_widget_driver.g.dart index bfdd60a..097c607 100644 --- a/widget_driver/example/lib/widgets/playground/playground_test_widget/playground_test_widget_driver.g.dart +++ b/widget_driver/example/lib/widgets/playground/playground_test_widget/playground_test_widget_driver.g.dart @@ -8,7 +8,7 @@ part of 'playground_test_widget_driver.dart'; // coverage:ignore-file -// This file was generated with widget_driver_generator version "1.3.6" +// This file was generated with widget_driver_generator version "1.4.0-pre.1" class _$TestPlaygroundTestWidgetDriver extends TestDriver implements PlaygroundTestWidgetDriver { @override diff --git a/widget_driver/example/pubspec.yaml b/widget_driver/example/pubspec.yaml index ddca71b..67d21ba 100644 --- a/widget_driver/example/pubspec.yaml +++ b/widget_driver/example/pubspec.yaml @@ -21,17 +21,12 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^1.0.4 + flutter_lints: ^2.0.1 mocktail: ^1.0.4 widget_driver_test: path: ../../widget_driver_test - build_runner: - widget_driver_generator: ^1.2.0 - -# Overrides the published widget_driver_generator with the local package, whose analyzer -# constraint was relaxed to resolve with newer Flutter SDKs (see widget_driver_generator/pubspec.yaml). -dependency_overrides: - widget_driver_generator: + build_runner: ^2.3.3 + widget_driver_generator: path: ../../widget_driver_generator flutter: diff --git a/widget_driver/example/test/driver_tests/coffee_consumption/coffee_counter/coffee_counter_header_section_driver_test.dart b/widget_driver/example/test/driver_tests/coffee_consumption/coffee_counter/coffee_counter_header_section_driver_test.dart index e6c5997..a607618 100644 --- a/widget_driver/example/test/driver_tests/coffee_consumption/coffee_counter/coffee_counter_header_section_driver_test.dart +++ b/widget_driver/example/test/driver_tests/coffee_consumption/coffee_counter/coffee_counter_header_section_driver_test.dart @@ -16,7 +16,7 @@ void main() { mockLocalization = MockLocalization(); }); - Future> _getDriver(WidgetTester tester) async { + Future> getDriver(WidgetTester tester) async { return tester.getDriverTester( driverBuilder: () => CoffeeCounterHeaderSectionDriver(), parentWidgetBuilder: (driverWidget) { @@ -42,14 +42,14 @@ void main() { const expectedText = 'Some text about consumed coffees'; when(() => mockLocalization.consumedCoffees).thenReturn(expectedText); - final driverTester = await _getDriver(tester); + final driverTester = await getDriver(tester); expect(driverTester.driver.descriptionText, expectedText); }); testWidgets('Has correct value for amountText', (tester) async { fakeCoffeeCountNotifier.value = 123; - final driverTester = await _getDriver(tester); + final driverTester = await getDriver(tester); expect(driverTester.driver.amountText, '123'); }); }); @@ -59,7 +59,7 @@ void main() { // The initial value used when driver is created fakeCoffeeCountNotifier.value = 123; - final driverTester = await _getDriver(tester); + final driverTester = await getDriver(tester); expect(driverTester.driver.amountText, '123'); // Set a new value to the coffee count and trigger widget tester to render the update. diff --git a/widget_driver_annotation/pubspec.yaml b/widget_driver_annotation/pubspec.yaml index 151522f..4a6d5f3 100644 --- a/widget_driver_annotation/pubspec.yaml +++ b/widget_driver_annotation/pubspec.yaml @@ -8,4 +8,4 @@ environment: sdk: ">=3.4.0 <4.0.0" dev_dependencies: - test: ^1.22.2 + test: ">=1.3.0 <2.0.0" diff --git a/widget_driver_generator/lib/builder.dart b/widget_driver_generator/lib/builder.dart index ff66c40..355b92a 100644 --- a/widget_driver_generator/lib/builder.dart +++ b/widget_driver_generator/lib/builder.dart @@ -15,6 +15,7 @@ Builder generateWidgetDriver(BuilderOptions options) { return SharedPartBuilder( [WidgetDriverGenerator(options: options)], 'widget_driver_generator', - formatOutput: DartFormatter(pageWidth: customLineLength).format, + formatOutput: (code, languageVersion) => + DartFormatter(languageVersion: languageVersion, pageWidth: customLineLength).format(code), ); } diff --git a/widget_driver_generator/lib/src/model_visitor.dart b/widget_driver_generator/lib/src/model_visitor.dart index c853f6a..76e9f5a 100644 --- a/widget_driver_generator/lib/src/model_visitor.dart +++ b/widget_driver_generator/lib/src/model_visitor.dart @@ -1,5 +1,5 @@ import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/dart/element/visitor.dart'; +import 'package:analyzer/dart/element/visitor2.dart'; import 'package:widget_driver_annotation/widget_driver_annotation.dart'; import 'models/annotated_element.dart'; @@ -11,7 +11,7 @@ import 'utils/property_accessor_element_extensions.dart'; typedef CodeGeneratorMethod = String Function(String codeDefinition, String returnValue); /// Inspect classes and get className, fields and all constructor parameters annotated with the @driverProvidableFields. -class ModelVisitor extends SimpleElementVisitor { +class ModelVisitor extends SimpleElementVisitor2 { String className = ""; final fields = []; final methods = []; @@ -35,7 +35,7 @@ class ModelVisitor extends SimpleElementVisitor { className = elementReturnType.replaceFirst('*', ''); if (!element.isFactory || !element.isDefaultConstructor) { - for (final param in element.parameters) { + for (final param in element.formalParameters) { if (_elementUtils.hasValidAnnotation( element: param, validAnnotationType: driverProvidableProperty.runtimeType, @@ -65,7 +65,12 @@ class ModelVisitor extends SimpleElementVisitor { } @override - void visitPropertyAccessorElement(PropertyAccessorElement element) { + void visitGetterElement(GetterElement element) => _visitPropertyAccessorElement(element); + + @override + void visitSetterElement(SetterElement element) => _visitPropertyAccessorElement(element); + + void _visitPropertyAccessorElement(PropertyAccessorElement element) { if (element.isStatic) { return; } diff --git a/widget_driver_generator/lib/src/models/providable_field.dart b/widget_driver_generator/lib/src/models/providable_field.dart index 3482220..563ef34 100644 --- a/widget_driver_generator/lib/src/models/providable_field.dart +++ b/widget_driver_generator/lib/src/models/providable_field.dart @@ -20,7 +20,7 @@ class ProvidableField { }); factory ProvidableField.fromParameterElement( - ParameterElement param, { + FormalParameterElement param, { ImportPrefixResolver importPrefixResolver = const ImportPrefixResolver(), }) { final rawType = param.type.toString().replaceFirst('*', ''); @@ -29,7 +29,7 @@ class ProvidableField { ? rawType : importPrefixResolver.applyPrefixes(code: rawType, types: [param.type], library: library); return ProvidableField( - name: param.name.removeLeadingUnderscore(), + name: param.name?.removeLeadingUnderscore() ?? "", type: type, isRequired: param.isRequired, defaultValueCode: param.defaultValueCode, diff --git a/widget_driver_generator/lib/src/utils/element_utils.dart b/widget_driver_generator/lib/src/utils/element_utils.dart index 7fcee2c..71f1c58 100644 --- a/widget_driver_generator/lib/src/utils/element_utils.dart +++ b/widget_driver_generator/lib/src/utils/element_utils.dart @@ -20,7 +20,7 @@ class ElementUtils { required List validAnnotationTypes, }) { for (var validAnnotationType in validAnnotationTypes) { - final annotation = TypeChecker.fromRuntime(validAnnotationType).firstAnnotationOfExact(element); + final annotation = TypeChecker.typeNamed(validAnnotationType).firstAnnotationOfExact(element); if (annotation != null) { return validAnnotationType; } @@ -61,10 +61,10 @@ class ElementUtils { return [element.type]; } if (element is PropertyAccessorElement) { - return [element.returnType, ...element.parameters.map((parameter) => parameter.type)]; + return [element.returnType, ...element.formalParameters.map((parameter) => parameter.type)]; } if (element is MethodElement) { - return [element.returnType, ...element.parameters.map((parameter) => parameter.type)]; + return [element.returnType, ...element.formalParameters.map((parameter) => parameter.type)]; } return const []; } @@ -91,7 +91,7 @@ class ElementUtils { } String _getAnnotationStringFromElement(Element element) { - final metaData = element.metadata.first; + final metaData = element.metadata.annotations.first; return metaData.toSource(); } diff --git a/widget_driver_generator/lib/src/utils/field_element_extensions.dart b/widget_driver_generator/lib/src/utils/field_element_extensions.dart index c65463f..42c4e5e 100644 --- a/widget_driver_generator/lib/src/utils/field_element_extensions.dart +++ b/widget_driver_generator/lib/src/utils/field_element_extensions.dart @@ -1,9 +1,6 @@ import 'package:analyzer/dart/element/element.dart'; -// ignore: implementation_imports -import 'package:analyzer/src/dart/element/element.dart'; extension FieldElementExtension on FieldElement { /// All getters are also treated as fields but have explicit getters. - bool get isRedundantToPropertyAccessorElement => - setter is! PropertyAccessorElementImpl_ImplicitSetter && getter is! PropertyAccessorElementImpl_ImplicitGetter; + bool get isRedundantToPropertyAccessorElement => setter?.isSynthetic != true && getter?.isSynthetic != true; } diff --git a/widget_driver_generator/lib/src/utils/import_prefix_resolver.dart b/widget_driver_generator/lib/src/utils/import_prefix_resolver.dart index 16f688f..97c68ee 100644 --- a/widget_driver_generator/lib/src/utils/import_prefix_resolver.dart +++ b/widget_driver_generator/lib/src/utils/import_prefix_resolver.dart @@ -96,7 +96,7 @@ class ImportPrefixResolver { } String? _findImportPrefix(LibraryElement library, LibraryElement typeLibrary) { - for (final import in library.libraryImports) { + for (final import in library.firstFragment.libraryImports) { final prefix = import.prefix; if (import.importedLibrary == typeLibrary && prefix != null) { return prefix.element.name; @@ -111,7 +111,7 @@ class ImportPrefixResolver { if (type is InterfaceType) { yield* _flatten(type.typeArguments); } else if (type is FunctionType) { - yield* _flatten([type.returnType, ...type.parameters.map((parameter) => parameter.type)]); + yield* _flatten([type.returnType, ...type.formalParameters.map((parameter) => parameter.type)]); } } } diff --git a/widget_driver_generator/lib/src/utils/property_accessor_element_extensions.dart b/widget_driver_generator/lib/src/utils/property_accessor_element_extensions.dart index 69ff68d..fce4b9c 100644 --- a/widget_driver_generator/lib/src/utils/property_accessor_element_extensions.dart +++ b/widget_driver_generator/lib/src/utils/property_accessor_element_extensions.dart @@ -1,12 +1,9 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; -// ignore: implementation_imports -import 'package:analyzer/src/dart/element/element.dart'; extension PropertyAccessorElementExtension on PropertyAccessorElement { /// All fields have implicit getters and setters. - bool get isRedundantToFieldElement => - this is PropertyAccessorElementImpl_ImplicitSetter || this is PropertyAccessorElementImpl_ImplicitGetter; + bool get isRedundantToFieldElement => isSynthetic; /// VoidType PropertyAccessorElements are setters. bool get isSetter => returnType is VoidType; diff --git a/widget_driver_generator/pubspec.yaml b/widget_driver_generator/pubspec.yaml index 9e5b0ca..c60951f 100644 --- a/widget_driver_generator/pubspec.yaml +++ b/widget_driver_generator/pubspec.yaml @@ -1,6 +1,6 @@ name: widget_driver_generator description: This package provides generators for WidgetDriver to automate the creation of your TestDrivers and WidgetDriverProviders -version: 1.3.7 +version: 1.4.0-pre.1 repository: https://github.com/bmw-tech/widget_driver/tree/master/widget_driver_generator issue_tracker: https://github.com/bmw-tech/widget_driver/issues @@ -13,15 +13,15 @@ environment: sdk: ">=3.4.0 <4.0.0" dependencies: - build: ^2.0.0 - source_gen: ^1.0.0 - analyzer: '>=5.13.0 <8.0.0' + build: ^4.0.0 + source_gen: 4.0.1 + analyzer: ^8.1.1 widget_driver_annotation: ^1.0.2 yaml: ^3.1.2 - dart_style: ^2.3.2 + dart_style: '>=2.3.2 <4.0.0' dev_dependencies: - build_runner: ^2.0.0 + build_runner: ^2.3.3 flutter_lints: ^2.0.1 - test: ^1.22.2 + test: ">=1.3.0 <2.0.0" mocktail: ^1.0.4 diff --git a/widget_driver_generator/test/models/providable_field_test.dart b/widget_driver_generator/test/models/providable_field_test.dart new file mode 100644 index 0000000..303ee00 --- /dev/null +++ b/widget_driver_generator/test/models/providable_field_test.dart @@ -0,0 +1,108 @@ +import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/type.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:test/test.dart'; +import 'package:widget_driver_generator/src/models/providable_field.dart'; + +class MockFormalParameterElement extends Mock implements FormalParameterElement {} + +class MockLibraryElement extends Mock implements LibraryElement {} + +class MockLibraryFragment extends Mock implements LibraryFragment {} + +class MockLibraryImport extends Mock implements LibraryImport {} + +class MockPrefixFragment extends Mock implements PrefixFragment {} + +class MockPrefixElement extends Mock implements PrefixElement {} + +class MockElement extends Mock implements Element {} + +// Mocktail's Mock can't stub `toString()`, but that's what ImportPrefixResolver reads the raw type +// name from, so this fake implements DartType directly (like `element.toString()` in production). +class FakeDartType implements DartType { + const FakeDartType(this._typeName, this.element); + + final String _typeName; + + @override + final Element element; + + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); + + @override + String toString() => _typeName; +} + +void main() { + group('ProvidableField.fromParameterElement:', () { + test('keeps the import alias for a parameter type imported with a prefix', () { + final typeLibrary = MockLibraryElement(); + final contextLibrary = MockLibraryElement(); + + final typeElement = MockElement(); + when(() => typeElement.name).thenReturn('SomeClass'); + when(() => typeElement.library).thenReturn(typeLibrary); + + final type = FakeDartType('SomeClass', typeElement); + + final prefixElement = MockPrefixElement(); + when(() => prefixElement.name).thenReturn('foo'); + final prefixFragment = MockPrefixFragment(); + when(() => prefixFragment.element).thenReturn(prefixElement); + + final import = MockLibraryImport(); + when(() => import.importedLibrary).thenReturn(typeLibrary); + when(() => import.prefix).thenReturn(prefixFragment); + + final fragment = MockLibraryFragment(); + when(() => fragment.libraryImports).thenReturn([import]); + when(() => contextLibrary.firstFragment).thenReturn(fragment); + + final param = MockFormalParameterElement(); + when(() => param.type).thenReturn(type); + when(() => param.library).thenReturn(contextLibrary); + when(() => param.name).thenReturn('someParam'); + when(() => param.isRequired).thenReturn(true); + when(() => param.isNamed).thenReturn(false); + when(() => param.defaultValueCode).thenReturn(null); + + final field = ProvidableField.fromParameterElement(param); + + expect(field.type, 'foo.SomeClass'); + expect(field.name, 'someParam'); + }); + + test('does not add a prefix if the parameter type was imported without an alias', () { + final typeLibrary = MockLibraryElement(); + final contextLibrary = MockLibraryElement(); + + final typeElement = MockElement(); + when(() => typeElement.name).thenReturn('SomeClass'); + when(() => typeElement.library).thenReturn(typeLibrary); + + final type = FakeDartType('SomeClass', typeElement); + + final import = MockLibraryImport(); + when(() => import.importedLibrary).thenReturn(typeLibrary); + when(() => import.prefix).thenReturn(null); + + final fragment = MockLibraryFragment(); + when(() => fragment.libraryImports).thenReturn([import]); + when(() => contextLibrary.firstFragment).thenReturn(fragment); + + final param = MockFormalParameterElement(); + when(() => param.type).thenReturn(type); + when(() => param.library).thenReturn(contextLibrary); + when(() => param.name).thenReturn('someParam'); + when(() => param.isRequired).thenReturn(true); + when(() => param.isNamed).thenReturn(false); + when(() => param.defaultValueCode).thenReturn(null); + + final field = ProvidableField.fromParameterElement(param); + + expect(field.type, 'SomeClass'); + }); + }); +} diff --git a/widget_driver_generator/test/utils/field_element_extensions_test.dart b/widget_driver_generator/test/utils/field_element_extensions_test.dart index 8de312a..33097bc 100644 --- a/widget_driver_generator/test/utils/field_element_extensions_test.dart +++ b/widget_driver_generator/test/utils/field_element_extensions_test.dart @@ -1,29 +1,32 @@ import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/src/dart/element/element.dart'; import 'package:test/test.dart'; import 'package:mocktail/mocktail.dart'; import 'package:widget_driver_generator/src/utils/field_element_extensions.dart'; class MockFieldElement extends Mock implements FieldElement {} -class MockPropertyAccessorElementImplImplicitSetter extends Mock - implements PropertyAccessorElementImpl_ImplicitSetter {} +class MockSetterElement extends Mock implements SetterElement {} -class MockPropertyAccessorElementImplImplicitGetter extends Mock - implements PropertyAccessorElementImpl_ImplicitGetter {} +class MockGetterElement extends Mock implements GetterElement {} void main() { group('FieldElementExtension: isRedundantToPropertyAccessorElement', () { test('returns false for a FieldElement with implicit setter and getter (aka variable field)', () { final sut = MockFieldElement(); - when(() => sut.setter).thenReturn(MockPropertyAccessorElementImplImplicitSetter()); - when(() => sut.getter).thenReturn(MockPropertyAccessorElementImplImplicitGetter()); + final setter = MockSetterElement(); + final getter = MockGetterElement(); + when(() => setter.isSynthetic).thenReturn(true); + when(() => getter.isSynthetic).thenReturn(true); + when(() => sut.setter).thenReturn(setter); + when(() => sut.getter).thenReturn(getter); expect(sut.isRedundantToPropertyAccessorElement, isFalse); }); test('returns false for a FieldElement with implicit getter (aka final field)', () { final sut = MockFieldElement(); - when(() => sut.getter).thenReturn(MockPropertyAccessorElementImplImplicitGetter()); + final getter = MockGetterElement(); + when(() => getter.isSynthetic).thenReturn(true); + when(() => sut.getter).thenReturn(getter); expect(sut.isRedundantToPropertyAccessorElement, isFalse); }); diff --git a/widget_driver_generator/test/utils/import_prefix_resolver_test.dart b/widget_driver_generator/test/utils/import_prefix_resolver_test.dart index 235a5d6..b42a459 100644 --- a/widget_driver_generator/test/utils/import_prefix_resolver_test.dart +++ b/widget_driver_generator/test/utils/import_prefix_resolver_test.dart @@ -6,9 +6,11 @@ import 'package:widget_driver_generator/src/utils/import_prefix_resolver.dart'; class MockLibraryElement extends Mock implements LibraryElement {} -class MockLibraryImportElement extends Mock implements LibraryImportElement {} +class MockLibraryFragment extends Mock implements LibraryFragment {} -class MockImportElementPrefix extends Mock implements ImportElementPrefix {} +class MockLibraryImport extends Mock implements LibraryImport {} + +class MockPrefixFragment extends Mock implements PrefixFragment {} class MockPrefixElement extends Mock implements PrefixElement {} @@ -31,6 +33,12 @@ void main() { typeLibrary = MockLibraryElement(); }); + void stubImports(MockLibraryElement library, List imports) { + final fragment = MockLibraryFragment(); + when(() => fragment.libraryImports).thenReturn(imports); + when(() => library.firstFragment).thenReturn(fragment); + } + MockDartType typeNamed(String name, LibraryElement library) { final element = MockElement(); when(() => element.name).thenReturn(name); @@ -40,17 +48,17 @@ void main() { return type; } - MockLibraryImportElement importOf(LibraryElement importedLibrary, {String? prefix}) { - final import = MockLibraryImportElement(); + MockLibraryImport importOf(LibraryElement importedLibrary, {String? prefix}) { + final import = MockLibraryImport(); when(() => import.importedLibrary).thenReturn(importedLibrary); if (prefix == null) { when(() => import.prefix).thenReturn(null); } else { final prefixElement = MockPrefixElement(); when(() => prefixElement.name).thenReturn(prefix); - final importPrefix = MockImportElementPrefix(); - when(() => importPrefix.element).thenReturn(prefixElement); - when(() => import.prefix).thenReturn(importPrefix); + final prefixFragment = MockPrefixFragment(); + when(() => prefixFragment.element).thenReturn(prefixElement); + when(() => import.prefix).thenReturn(prefixFragment); } return import; } @@ -59,7 +67,7 @@ void main() { test('adds the alias in front of a type imported with a prefix', () { final import = importOf(typeLibrary, prefix: 'foo'); final type = typeNamed('SomeClass', typeLibrary); - when(() => contextLibrary.libraryImports).thenReturn([import]); + stubImports(contextLibrary, [import]); final result = sut.applyPrefixes( code: 'SomeClass get someGetter', @@ -71,7 +79,7 @@ void main() { }); test('does not change code if the type is declared in the same library', () { - when(() => contextLibrary.libraryImports).thenReturn([]); + stubImports(contextLibrary, []); final type = typeNamed('SomeClass', contextLibrary); final result = sut.applyPrefixes( @@ -86,7 +94,7 @@ void main() { test('does not change code if the import has no prefix', () { final import = importOf(typeLibrary); final type = typeNamed('SomeClass', typeLibrary); - when(() => contextLibrary.libraryImports).thenReturn([import]); + stubImports(contextLibrary, [import]); final result = sut.applyPrefixes( code: 'SomeClass get someGetter', @@ -107,7 +115,7 @@ void main() { final listType = MockInterfaceType(); when(() => listType.element).thenReturn(listElement); when(() => listType.typeArguments).thenReturn([typeArgument]); - when(() => contextLibrary.libraryImports).thenReturn([import]); + stubImports(contextLibrary, [import]); final result = sut.applyPrefixes( code: 'void doSomething(List list)', @@ -121,7 +129,7 @@ void main() { test('does not re-prefix a name that is already qualified', () { final import = importOf(typeLibrary, prefix: 'foo'); final type = typeNamed('SomeClass', typeLibrary); - when(() => contextLibrary.libraryImports).thenReturn([import]); + stubImports(contextLibrary, [import]); final result = sut.applyPrefixes( code: 'bar.SomeClass get someGetter', @@ -135,7 +143,7 @@ void main() { test('does not prefix an occurrence of the type name inside a string literal', () { final import = importOf(typeLibrary, prefix: 'foo'); final type = typeNamed('SomeClass', typeLibrary); - when(() => contextLibrary.libraryImports).thenReturn([import]); + stubImports(contextLibrary, [import]); final result = sut.applyPrefixes( code: "const SomeClass(name: 'SomeClass')", diff --git a/widget_driver_generator/test/utils/property_accessor_element_extensions_test.dart b/widget_driver_generator/test/utils/property_accessor_element_extensions_test.dart index b50eec6..920fa09 100644 --- a/widget_driver_generator/test/utils/property_accessor_element_extensions_test.dart +++ b/widget_driver_generator/test/utils/property_accessor_element_extensions_test.dart @@ -1,32 +1,22 @@ import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/src/dart/element/element.dart'; import 'package:test/test.dart'; import 'package:mocktail/mocktail.dart'; import 'package:widget_driver_generator/src/utils/property_accessor_element_extensions.dart'; class MockPropertyAccessorElement extends Mock implements PropertyAccessorElement {} -class MockPropertyAccessorElementImplImplicitSetter extends Mock - implements PropertyAccessorElementImpl_ImplicitSetter {} - -class MockPropertyAccessorElementImplImplicitGetter extends Mock - implements PropertyAccessorElementImpl_ImplicitGetter {} - void main() { group('PropertyAccessorElementExtension:', () { group('isRedundantToFieldElement:', () { - test('returns false for a PropertyAccessorElementImpl_ImplicitSetter', () { - final sut = MockPropertyAccessorElementImplImplicitSetter(); - expect(sut.isRedundantToFieldElement, isTrue); - }); - - test('returns false for a PropertyAccessorElementImpl_ImplicitGetter', () { - final sut = MockPropertyAccessorElementImplImplicitGetter(); + test('returns true for a synthetic (implicit) PropertyAccessorElement', () { + final sut = MockPropertyAccessorElement(); + when(() => sut.isSynthetic).thenReturn(true); expect(sut.isRedundantToFieldElement, isTrue); }); - test('returns false for a PropertyAccessorElement', () { + test('returns false for a non-synthetic (explicit) PropertyAccessorElement', () { final sut = MockPropertyAccessorElement(); + when(() => sut.isSynthetic).thenReturn(false); expect(sut.isRedundantToFieldElement, isFalse); }); }); diff --git a/widget_driver_test/pubspec.yaml b/widget_driver_test/pubspec.yaml index 5c3f8a3..90dd571 100644 --- a/widget_driver_test/pubspec.yaml +++ b/widget_driver_test/pubspec.yaml @@ -15,7 +15,7 @@ dependencies: widget_driver: ^1.0.8 mocktail: ^1.0.4 meta: ^1.7.0 - test: ^1.22.2 dev_dependencies: flutter_lints: ^1.0.4 + test: ^1.22.2