diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..2fdc780 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,45 @@ +name: CI + +on: + push: + branches: + - 'master' + - 'test_consume_*' + tags: + - '**' + pull_request: + branches: + - '**' + +jobs: + dart: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [ 2.19.6, stable ] + name: Dart ${{ matrix.sdk }} + steps: + - uses: actions/checkout@v4 + - uses: dart-lang/setup-dart@v1 + with: + sdk: ${{ matrix.sdk }} + - name: Install dependencies + run: dart pub get + - name: Validate dependencies + run: dart run dependency_validator + - name: Analysis + run: dart analyze + - name: Formatting + run: dart format --set-exit-if-changed . + if: ${{ matrix.sdk == 'stable' }} + - name: Tests + run: dart run dart_dev test + - name: Tests (dart2js) + run: dart run dart_dev test --release + - name: SBOM + if: ${{ matrix.sdk == 'stable' }} + uses: anchore/sbom-action@v0 + with: + path: ./ + format: cyclonedx-json diff --git a/.github/workflows/dart_ci.yml b/.github/workflows/dart_ci.yml deleted file mode 100644 index 76d443b..0000000 --- a/.github/workflows/dart_ci.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: Dart CI - -on: - push: - branches: - - 'master' - - 'test_consume_*' - tags: - - '**' - pull_request: - branches: - - '**' - -jobs: - build: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - sdk: [ 2.19.6 ] - steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.2 - with: - sdk: ${{ matrix.sdk }} - - - id: install - name: Install dependencies - run: dart pub get - - - name: Validate dependencies - run: dart run dependency_validator - if: always() && steps.install.outcome == 'success' - - - name: Analyze project source - run: dart analyze - if: always() && steps.install.outcome == 'success' - - - name: Run tests with ddc - run: dart run dart_dev test - if: always() && steps.install.outcome == 'success' - - - name: Run tests with dart2js - run: dart run dart_dev test --release - if: always() && steps.install.outcome == 'success' - - - name: Verify formatting - run: dart format --set-exit-if-changed . - if: always() && steps.install.outcome == 'success' - - - name: SBOM - if: ${{ matrix.sdk == '2.19.6' }} - uses: anchore/sbom-action@v0 - with: - path: ./ - format: cyclonedx-json diff --git a/analysis_options.yaml b/analysis_options.yaml index 674d744..04067cf 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,715 +1,8 @@ -# analysis_options.yaml docs: https://www.dartlang.org/guides/language/analysis-options +include: package:workiva_analysis_options/v2.recommended.yaml + analyzer: exclude: - "example/**" - "w_flux_codemod/**" - language: strict-casts: true - -# ALL lint rules are included. Unused lints should be commented -# out with a reason. An up to date list of all options is here -# http://dart-lang.github.io/linter/lints/options/options.html -# Descriptions of each rule is here http://dart-lang.github.io/linter/lints/ -# -# To ignore a lint rule on a case by case basic in code just add a comment -# above it or at the end of the line like: // ignore: -# example: // ignore: invalid_assignment, const_initialized_with_non_constant_value -# -# More info about configuring analysis_options.yaml files -# https://www.dartlang.org/guides/language/analysis-options#excluding-lines-within-a-file -linter: - rules: - # Declare method return types. - # http://dart-lang.github.io/linter/lints/always_declare_return_types.html - # recommendation: recommended - # reason: React component render() method can return either ReactElement or false - # FIXME: 29 lint(s) - # - always_declare_return_types - - # Separate the control structure expression from its statement. - # http://dart-lang.github.io/linter/lints/always_put_control_body_on_new_line.html - # recommendation: optional - # FIXME: 6 lint(s) - # - always_put_control_body_on_new_line - - # Put @required named parameters first. - # http://dart-lang.github.io/linter/lints/always_put_required_named_parameters_first.html - # recommendation: recommended - # 0 issues - - always_put_required_named_parameters_first - - # Use @required. - # http://dart-lang.github.io/linter/lints/always_require_non_null_named_parameters.html - # recommendation: recommended - # 0 issues - - always_require_non_null_named_parameters - - # Specify type annotations. - # http://dart-lang.github.io/linter/lints/always_specify_types.html - # recommendation: optional - # FIXME: 119 lint(s) - # - always_specify_types - - # Annotate overridden members. - # http://dart-lang.github.io/linter/lints/annotate_overrides.html - # recommendation: required - # FIXME: 1 lint(s) - - annotate_overrides - - # Avoid annotating with dynamic when not required. - # http://dart-lang.github.io/linter/lints/avoid_annotating_with_dynamic.html - # recommendation: optional - # 0 issues - - avoid_annotating_with_dynamic - - # Avoid using `as`. - # http://dart-lang.github.io/linter/lints/avoid_as.html - # recommendation: optional - # FIXME: 10 lint(s) - # - avoid_as - - # Avoid bool literals in conditional expressions. - # http://dart-lang.github.io/linter/lints/avoid_bool_literals_in_conditional_expressions.html - # recommendation: optional - # 0 issues - - avoid_bool_literals_in_conditional_expressions - - # Avoid catches without on clauses. - # http://dart-lang.github.io/linter/lints/avoid_catches_without_on_clauses.html - # recommendation: optional - # 0 issues - - avoid_catches_without_on_clauses - - # Don't explicitly catch Error or types that implement it. - # http://dart-lang.github.io/linter/lints/avoid_catching_errors.html - # recommendation: optional - # 0 issues - - avoid_catching_errors - - # Avoid defining a class that contains only static members. - # http://dart-lang.github.io/linter/lints/avoid_classes_with_only_static_members.html - # recommendation: recommended - # 0 issues - - avoid_classes_with_only_static_members - - # Avoid double and int checks. - # http://dart-lang.github.io/linter/lints/avoid_double_and_int_checks.html - # recommendation: required - # 0 issues - - avoid_double_and_int_checks - - # Avoid empty else statements. - # http://dart-lang.github.io/linter/lints/avoid_empty_else.html - # recommendation: required - # 0 issues - - avoid_empty_else - - # Avoid field initializers in const classes. - # http://dart-lang.github.io/linter/lints/avoid_field_initializers_in_const_classes.html - # recommendation: optional - # 0 issues - - avoid_field_initializers_in_const_classes - - # Avoid using `forEach` with a function literal. - # http://dart-lang.github.io/linter/lints/avoid_function_literals_in_foreach_calls.html - # recommendation: recommended - # reason: Use for (x in y) or forEach(someFunc) instead - # FIXME: 1 lint(s) - # - avoid_function_literals_in_foreach_calls - - # Don't explicitly initialize variables to null. - # http://dart-lang.github.io/linter/lints/avoid_init_to_null.html - # recommendation: recommended - # 0 issues - - avoid_init_to_null - - # Avoid JavaScript rounded ints. - # http://dart-lang.github.io/linter/lints/avoid_js_rounded_ints.html - # recommendation: optional - # 0 issues - - avoid_js_rounded_ints - - # Don't check for null in custom == operators. - # http://dart-lang.github.io/linter/lints/avoid_null_checks_in_equality_operators.html - # recommendation: recommended - # 0 issues - - avoid_null_checks_in_equality_operators - - # Avoid positional boolean parameters. - # http://dart-lang.github.io/linter/lints/avoid_positional_boolean_parameters.html - # recommendation: recommended - # 0 issues - - avoid_positional_boolean_parameters - - # Avoid private typedef functions. - # http://dart-lang.github.io/linter/lints/avoid_private_typedef_functions.html - # recommendation: optional - # 0 issues - - avoid_private_typedef_functions - - # Avoid relative imports for files in `lib/`. - # http://dart-lang.github.io/linter/lints/avoid_relative_lib_imports.html - # recommendation: recommended - # reason: JS compilation will be faster without relative imports. Use package imports. - # 0 issues - - avoid_relative_lib_imports - - # Don't rename parameters of overridden methods. - # http://dart-lang.github.io/linter/lints/avoid_renaming_method_parameters.html - # recommendation: recommended - # 0 issues - - avoid_renaming_method_parameters - - # Avoid return types on setters. - # http://dart-lang.github.io/linter/lints/avoid_return_types_on_setters.html - # recommendation: required - # 0 issues - - avoid_return_types_on_setters - - # Avoid returning null from members whose return type is bool, double, int, or num. - # http://dart-lang.github.io/linter/lints/avoid_returning_null.html - # recommendation: recommended - # 0 issues - - avoid_returning_null - - # Avoid returning this from methods just to enable a fluent interface. - # http://dart-lang.github.io/linter/lints/avoid_returning_this.html - # recommendation: recommended - # 0 issues - - avoid_returning_this - - # Avoid setters without getters. - # http://dart-lang.github.io/linter/lints/avoid_setters_without_getters.html - # recommendation: recommended - # 0 issues - - avoid_setters_without_getters - - # Avoid single cascade in expression statements. - # http://dart-lang.github.io/linter/lints/avoid_single_cascade_in_expression_statements.html - # recommendation: optional - # 0 issues - - avoid_single_cascade_in_expression_statements - - # Avoid slow async `dart:io` methods. - # http://dart-lang.github.io/linter/lints/avoid_slow_async_io.html - # recommendation: recommended - # 0 issues - - avoid_slow_async_io - - # Avoid types as parameter names. - # http://dart-lang.github.io/linter/lints/avoid_types_as_parameter_names.html - # recommendation: required - # 0 issues - - avoid_types_as_parameter_names - - # Avoid annotating types for function expression parameters. - # http://dart-lang.github.io/linter/lints/avoid_types_on_closure_parameters.html - # recommendation: optional - # FIXME: 3 lint(s) - # - avoid_types_on_closure_parameters - - # Avoid defining unused paramters in constructors. - # http://dart-lang.github.io/linter/lints/avoid_unused_constructor_parameters.html - # recommendation: recommended - # 0 issues - - avoid_unused_constructor_parameters - - # Await only futures. - # http://dart-lang.github.io/linter/lints/await_only_futures.html - # recommendation: required - # 0 issues - - await_only_futures - - # Name types using UpperCamelCase. - # http://dart-lang.github.io/linter/lints/camel_case_types.html - # recommendation: required - # 0 issues - - camel_case_types - - # Cancel instances of dart.async.StreamSubscription. - # http://dart-lang.github.io/linter/lints/cancel_subscriptions.html - # recommendation: required - # 0 issues - - cancel_subscriptions - - # Cascade consecutive method invocations on the same reference. - # http://dart-lang.github.io/linter/lints/cascade_invocations.html - # recommendation: optional - # 0 issues - - cascade_invocations - - # Close instances of `dart.core.Sink`. - # http://dart-lang.github.io/linter/lints/close_sinks.html - # recommendation: required - # 0 issues - - close_sinks - - # Only reference in scope identifiers in doc comments. - # http://dart-lang.github.io/linter/lints/comment_references.html - # recommendation: recommended - # FIXME: 20 lint(s) - # - comment_references - - # Prefer using lowerCamelCase for constant names. - # http://dart-lang.github.io/linter/lints/constant_identifier_names.html - # recommendation: optional - # 0 issues - - constant_identifier_names - - # Avoid control flow in finally blocks. - # http://dart-lang.github.io/linter/lints/control_flow_in_finally.html - # recommendation: required - # 0 issues - - control_flow_in_finally - - # Adhere to Effective Dart Guide directives sorting conventions. - # http://dart-lang.github.io/linter/lints/directives_ordering.html - # recommendation: recommended - # FIXME: 1 lint(s) - # - directives_ordering - - # Avoid empty catch blocks. - # http://dart-lang.github.io/linter/lints/empty_catches.html - # recommendation: required - # 0 issues - - empty_catches - - # Use `;` instead of `{}` for empty constructor bodies. - # http://dart-lang.github.io/linter/lints/empty_constructor_bodies.html - # recommendation: recommended - # 0 issues - - empty_constructor_bodies - - # Avoid empty statements. - # http://dart-lang.github.io/linter/lints/empty_statements.html - # recommendation: required - # 0 issues - - empty_statements - - # Always override `hashCode` if overriding `==`. - # http://dart-lang.github.io/linter/lints/hash_and_equals.html - # recommendation: required - # FIXME: 1 lint(s) - - hash_and_equals - - # Don't import implementation files from another package. - # http://dart-lang.github.io/linter/lints/implementation_imports.html - # recommendation: required - # 0 issues - - implementation_imports - - # Conditions should not unconditionally evaluate to `true` or to `false`. - # http://dart-lang.github.io/linter/lints/invariant_booleans.html - # recommendation: required - # 0 issues - - invariant_booleans - - # Invocation of Iterable.contains with references of unrelated types. - # http://dart-lang.github.io/linter/lints/iterable_contains_unrelated_type.html - # recommendation: required - # 0 issues - - iterable_contains_unrelated_type - - # Join return statement with assignment when possible. - # http://dart-lang.github.io/linter/lints/join_return_with_assignment.html - # recommendation: optional - # 0 issues - - join_return_with_assignment - - # Name libraries and source files using `lowercase_with_underscores`. - # http://dart-lang.github.io/linter/lints/library_names.html - # recommendation: recommended - # 0 issues - - library_names - - # Use `lowercase_with_underscores` when specifying a library prefix. - # http://dart-lang.github.io/linter/lints/library_prefixes.html - # recommendation: recommended - # 0 issues - - library_prefixes - - # Invocation of `remove` with references of unrelated types. - # http://dart-lang.github.io/linter/lints/list_remove_unrelated_type.html - # recommendation: required - # 0 issues - - list_remove_unrelated_type - - # Boolean expression composed only with literals. - # http://dart-lang.github.io/linter/lints/literal_only_boolean_expressions.html - # recommendation: required - # 0 issues - - literal_only_boolean_expressions - - # Don't use adjacent strings in list. - # http://dart-lang.github.io/linter/lints/no_adjacent_strings_in_list.html - # recommendation: required - # 0 issues - - no_adjacent_strings_in_list - - # Don't use more than one case with same value. - # http://dart-lang.github.io/linter/lints/no_duplicate_case_values.html - # recommendation: required - # 0 issues - - no_duplicate_case_values - - # Name non-constant identifiers using lowerCamelCase. - # http://dart-lang.github.io/linter/lints/non_constant_identifier_names.html - # recommendation: recommended - # 0 issues - - non_constant_identifier_names - - # Omit type annotations for local variables. - # http://dart-lang.github.io/linter/lints/omit_local_variable_types.html - # recommendation: optional - # reason: Conflicts with always_specify_types. Recommend commenting this one out. - # FIXME: 53 lint(s) - # - omit_local_variable_types - - # Avoid defining a one-member abstract class when a simple function will do. - # http://dart-lang.github.io/linter/lints/one_member_abstracts.html - # recommendation: optional - # 0 issues - - one_member_abstracts - - # Only throw instances of classes extending either Exception or Error. - # http://dart-lang.github.io/linter/lints/only_throw_errors.html - # recommendation: required - # 0 issues - - only_throw_errors - - # Don't override fields. - # http://dart-lang.github.io/linter/lints/overridden_fields.html - # recommendation: optional - # 0 issues - - overridden_fields - - # Provide doc comments for all public APIs. - # http://dart-lang.github.io/linter/lints/package_api_docs.html - # recommendation: optional - # 0 issues - - package_api_docs - - # Use `lowercase_with_underscores` for package names. - # http://dart-lang.github.io/linter/lints/package_names.html - # recommendation: recommended - # 0 issues - - package_names - - # Prefix library names with the package name and a dot-separated path. - # http://dart-lang.github.io/linter/lints/package_prefixed_library_names.html - # recommendation: recommended - # 0 issues - - package_prefixed_library_names - - # Don't reassign references to parameters of functions or methods. - # http://dart-lang.github.io/linter/lints/parameter_assignments.html - # recommendation: optional - # 0 issues - - parameter_assignments - - # Use adjacent strings to concatenate string literals. - # http://dart-lang.github.io/linter/lints/prefer_adjacent_string_concatenation.html - # recommendation: optional - # 0 issues - - prefer_adjacent_string_concatenation - - # Prefer putting asserts in initializer list. - # http://dart-lang.github.io/linter/lints/prefer_asserts_in_initializer_lists.html - # recommendation: optional - # 0 issues - - prefer_asserts_in_initializer_lists - - # Use collection literals when possible. - # http://dart-lang.github.io/linter/lints/prefer_collection_literals.html - # recommendation: recommended - # 0 issues - - prefer_collection_literals - - # Prefer using `??=` over testing for null. - # http://dart-lang.github.io/linter/lints/prefer_conditional_assignment.html - # recommendation: optional - # 0 issues - - prefer_conditional_assignment - - # Prefer const with constant constructors. - # http://dart-lang.github.io/linter/lints/prefer_const_constructors.html - # recommendation: optional - # 0 issues - - prefer_const_constructors - - # Prefer declare const constructors on `@immutable` classes. - # http://dart-lang.github.io/linter/lints/prefer_const_constructors_in_immutables.html - # recommendation: optional - # 0 issues - - prefer_const_constructors_in_immutables - - # Prefer const over final for declarations. - # http://dart-lang.github.io/linter/lints/prefer_const_declarations.html - # recommendation: recommended - # 0 issues - - prefer_const_declarations - - # Prefer const literals as parameters of constructors on @immutable classes. - # http://dart-lang.github.io/linter/lints/prefer_const_literals_to_create_immutables.html - # recommendation: optional - # 0 issues - - prefer_const_literals_to_create_immutables - - # Prefer defining constructors instead of static methods to create instances. - # http://dart-lang.github.io/linter/lints/prefer_constructors_over_static_methods.html - # recommendation: optional - # 0 issues - - prefer_constructors_over_static_methods - - # Use contains for `List` and `String` instances. - # http://dart-lang.github.io/linter/lints/prefer_contains.html - # recommendation: recommended - # 0 issues - - prefer_contains - - # Prefer equal for default values. - # http://dart-lang.github.io/linter/lints/prefer_equal_for_default_values.html - # recommendation: optional - # 0 issues - - prefer_equal_for_default_values - - # Use => for short members whose body is a single return statement. - # http://dart-lang.github.io/linter/lints/prefer_expression_function_bodies.html - # recommendation: optional - # FIXME: 3 lint(s) - # - prefer_expression_function_bodies - - # Private field could be final. - # http://dart-lang.github.io/linter/lints/prefer_final_fields.html - # recommendation: optional - # FIXME: 2 lint(s) - # - prefer_final_fields - - # Prefer final for variable declaration if reference is not reassigned. - # http://dart-lang.github.io/linter/lints/prefer_final_locals.html - # recommendation: optional - # reason: Generates a lot of lint since people use var a lot for local variables. - # FIXME: 62 lint(s) - # - prefer_final_locals - - # Use `forEach` to only apply a function to all the elements. - # http://dart-lang.github.io/linter/lints/prefer_foreach.html - # recommendation: optional - # 0 issues - - prefer_foreach - - # Use a function declaration to bind a function to a name. - # http://dart-lang.github.io/linter/lints/prefer_function_declarations_over_variables.html - # recommendation: recommended - # 0 issues - - prefer_function_declarations_over_variables - - # Prefer generic function type aliases. - # http://dart-lang.github.io/linter/lints/prefer_generic_function_type_aliases.html - # recommendation: optional - # FIXME: 1 lint(s) - # - prefer_generic_function_type_aliases - - # Use initializing formals when possible. - # http://dart-lang.github.io/linter/lints/prefer_initializing_formals.html - # recommendation: recommended - # 0 issues - - prefer_initializing_formals - - # Use interpolation to compose strings and values. - # http://dart-lang.github.io/linter/lints/prefer_interpolation_to_compose_strings.html - # recommendation: optional - # 0 issues - - prefer_interpolation_to_compose_strings - - # Use `isEmpty` for Iterables and Maps. - # http://dart-lang.github.io/linter/lints/prefer_is_empty.html - # recommendation: required - # 0 issues - - prefer_is_empty - - # Use `isNotEmpty` for Iterables and Maps. - # http://dart-lang.github.io/linter/lints/prefer_is_not_empty.html - # recommendation: required - # 0 issues - - prefer_is_not_empty - - # Prefer to use whereType on iterable. - # http://dart-lang.github.io/linter/lints/prefer_iterable_whereType.html - # recommendation: optional - # reason: Optional for now since it is only available in Dart 2 - # 0 issues - - prefer_iterable_whereType - - # Prefer single quotes where they won't require escape sequences. - # http://dart-lang.github.io/linter/lints/prefer_single_quotes.html - # recommendation: recommended - # 0 issues - - prefer_single_quotes - - # Prefer typing uninitialized variables and fields. - # http://dart-lang.github.io/linter/lints/prefer_typing_uninitialized_variables.html - # recommendation: required - # FIXME: 1 lint(s) - - prefer_typing_uninitialized_variables - - # Document all public members. - # http://dart-lang.github.io/linter/lints/public_member_api_docs.html - # recommendation: optional - # reason: Can get annoying for React component lifecycle methods, constructors. - # FIXME: 6 lint(s) - # - public_member_api_docs - - # Property getter recursively returns itself. - # http://dart-lang.github.io/linter/lints/recursive_getters.html - # recommendation: optional - # 0 issues - - recursive_getters - - # Prefer using /// for doc comments. - # http://dart-lang.github.io/linter/lints/slash_for_doc_comments.html - # recommendation: recommended - # 0 issues - - slash_for_doc_comments - - # Sort constructor declarations before method declarations. - # http://dart-lang.github.io/linter/lints/sort_constructors_first.html - # recommendation: optional - # 0 issues - - sort_constructors_first - - # Sort unnamed constructor declarations first. - # http://dart-lang.github.io/linter/lints/sort_unnamed_constructors_first.html - # recommendation: optional - # 0 issues - - sort_unnamed_constructors_first - - # Test type arguments in operator ==(Object other). - # http://dart-lang.github.io/linter/lints/test_types_in_equals.html - # recommendation: required - # 0 issues - - test_types_in_equals - - # Avoid `throw` in finally block. - # http://dart-lang.github.io/linter/lints/throw_in_finally.html - # recommendation: required - # 0 issues - - throw_in_finally - - # Type annotate public APIs. - # http://dart-lang.github.io/linter/lints/type_annotate_public_apis.html - # recommendation: recommended - # reason: React component render() method can return either ReactElement or false. Use overrides. - # FIXME: 29 lint(s) - # - type_annotate_public_apis - - # Don't type annotate initializing formals. - # http://dart-lang.github.io/linter/lints/type_init_formals.html - # recommendation: optional - # 0 issues - - type_init_formals - - # Await future-returning functions inside async function bodies. - # http://dart-lang.github.io/linter/lints/unawaited_futures.html - # recommendation: recommended - # 0 issues - - unawaited_futures - - # Avoid using braces in interpolation when not needed. - # http://dart-lang.github.io/linter/lints/unnecessary_brace_in_string_interps.html - # recommendation: optional - # 0 issues - - unnecessary_brace_in_string_interps - - # Avoid wrapping fields in getters and setters just to be "safe". - # http://dart-lang.github.io/linter/lints/unnecessary_getters_setters.html - # recommendation: optional - # 0 issues - - unnecessary_getters_setters - - # Don't create a lambda when a tear-off will do. - # http://dart-lang.github.io/linter/lints/unnecessary_lambdas.html - # recommendation: recommended - # 0 issues - - unnecessary_lambdas - - # Avoid null in null-aware assignment. - # http://dart-lang.github.io/linter/lints/unnecessary_null_aware_assignments.html - # recommendation: required - # 0 issues - - unnecessary_null_aware_assignments - - # Avoid using `null` in `if null` operators. - # http://dart-lang.github.io/linter/lints/unnecessary_null_in_if_null_operators.html - # recommendation: required - # 0 issues - - unnecessary_null_in_if_null_operators - - # Don't override a method to do a super method invocation with the same parameters. - # http://dart-lang.github.io/linter/lints/unnecessary_overrides.html - # recommendation: optional - # 0 issues - - unnecessary_overrides - - # Unnecessary parenthesis can be removed. - # http://dart-lang.github.io/linter/lints/unnecessary_parenthesis.html - # recommendation: optional - # 0 issues - - unnecessary_parenthesis - - # Avoid using unnecessary statements. - # http://dart-lang.github.io/linter/lints/unnecessary_statements.html - # recommendation: required - # 0 issues - - unnecessary_statements - - # Don't access members with `this` unless avoiding shadowing. - # http://dart-lang.github.io/linter/lints/unnecessary_this.html - # recommendation: recommended - # 0 issues - - unnecessary_this - - # Equality operator `==` invocation with references of unrelated types. - # http://dart-lang.github.io/linter/lints/unrelated_type_equality_checks.html - # recommendation: required - # reason: Comparing references of a type where neither is a subtype of the other most likely will return false and might not reflect programmer's intent. - # 0 issues - - unrelated_type_equality_checks - - # Use rethrow to rethrow a caught exception. - # http://dart-lang.github.io/linter/lints/use_rethrow_when_possible.html - # recommendation: recommended - # 0 issues - - use_rethrow_when_possible - - # Use a setter for operations that conceptually change a property. - # http://dart-lang.github.io/linter/lints/use_setters_to_change_properties.html - # recommendation: optional - # 0 issues - - use_setters_to_change_properties - - # Use string buffer to compose strings. - # http://dart-lang.github.io/linter/lints/use_string_buffers.html - # recommendation: optional - # 0 issues - - use_string_buffers - - # Start the name of the method with to/_to or as/_as if applicable. - # http://dart-lang.github.io/linter/lints/use_to_and_as_if_applicable.html - # recommendation: optional - # 0 issues - - use_to_and_as_if_applicable - - # Use valid regular expression syntax. - # http://dart-lang.github.io/linter/lints/valid_regexps.html - # recommendation: required - # 0 issues - - valid_regexps - - # Don't assign to void. - # http://dart-lang.github.io/linter/lints/void_checks.html - # recommendation: required - # reason: Trying to assigning a value to void is an error. - # 0 issues - - void_checks diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 4af28e8..f92a280 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -5,9 +5,10 @@ description: Flux library for uni-directional dataflow inspired by reflux and Fa homepage: https://github.com/Workiva/w_flux publish_to: none environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.19.0 <4.0.0' + dependencies: - w_flux: + w_flux: dev_dependencies: react: ^7.0.0 diff --git a/lib/src/action.dart b/lib/src/action.dart index efa5709..14aa0a9 100644 --- a/lib/src/action.dart +++ b/lib/src/action.dart @@ -56,11 +56,12 @@ class Action extends ActionV2 { /// when a consumer needs to check state changes immediately after invoking an /// action. /// -class ActionV2 extends Object with Disposable implements Function { +// ignore: prefer_mixin +class ActionV2 extends Object with Disposable { @override String get disposableTypeName => 'ActionV2'; - List<_ActionListener> _listeners = []; + final _listeners = <_ActionListener>[]; /// Dispatch this [ActionV2] to all listeners. The payload will be passed to /// each listener's callback. @@ -99,11 +100,14 @@ class ActionV2 extends Object with Disposable implements Function { } @override + // ignore: prefer_void_to_null Future onDispose() async { _listeners.clear(); } /// Actions are only deemed equivalent if they are the exact same Object + @override + // ignore: hash_and_equals bool operator ==(Object other) { return identical(this, other); } diff --git a/lib/src/component_client.dart b/lib/src/component_client.dart index a1f12b6..454563c 100644 --- a/lib/src/component_client.dart +++ b/lib/src/component_client.dart @@ -16,17 +16,19 @@ library w_flux.src.component_client; import 'package:meta/meta.dart'; +import 'package:w_flux/src/action.dart'; import 'package:w_flux/src/component_common.dart'; import 'package:w_flux/src/mixins/batched_redraws.dart'; import 'package:w_flux/src/store.dart'; /// FluxComponents are responsible for rendering application views and turning -/// user interactions and events into [Action]s. FluxComponents can use data +/// user interactions and events into [ActionV2]s. FluxComponents can use data /// from one or many [Store] instances to define the resulting component. /// /// This FluxComponent, intended for use on the client, utilizes the /// [BatchedRedraws] mixin to throttle redraws down to one per animation frame. abstract class FluxComponent + // ignore: prefer_mixin extends FluxComponentCommon with BatchedRedraws { @mustCallSuper @override diff --git a/lib/src/component_common.dart b/lib/src/component_common.dart index ad12634..1d63427 100644 --- a/lib/src/component_common.dart +++ b/lib/src/component_common.dart @@ -20,21 +20,25 @@ import 'package:meta/meta.dart'; import 'package:react/react.dart' as react; import 'package:w_common/disposable.dart'; +import 'package:w_flux/src/action.dart'; import 'package:w_flux/src/constants.dart' show v3Deprecation; import 'package:w_flux/src/store.dart'; /// FluxComponents are responsible for rendering application views and turning -/// user interactions and events into [Action]s. FluxComponents can use data +/// user interactions and events into [ActionV2]s. FluxComponents can use data /// from one or many [Store] instances to define the resulting component. +// ignore: deprecated_member_use abstract class FluxComponentCommon extends react.Component - with Disposable { - /// The class instance defined by [ActionsT] that holds all [Action]s that + with + // ignore: prefer_mixin + Disposable { + /// The class instance defined by [ActionsT] that holds all [ActionV2]s that /// this component needs access to. /// /// There is no strict rule on the [ActionsT] type. Depending on application - /// structure, there may be [Action]s available directly on this object, or + /// structure, there may be [ActionV2]s available directly on this object, or /// this object may represent a hierarchy of actions. - ActionsT get actions => this.props['actions'] as ActionsT; + ActionsT get actions => props['actions'] as ActionsT; /// The class instance defined by [StoresT]. This object should either be an /// instance of [Store] or should provide access to one or more [Store]s. @@ -52,7 +56,7 @@ abstract class FluxComponentCommon extends react.Component /// [StoresT] should be a class that provides access to these multiple stores. /// Then, you can explicitly select the [Store] instances that should be /// listened to by overriding [redrawOn]. - StoresT get store => this.props['store'] as StoresT; + StoresT get store => props['store'] as StoresT; @mustCallSuper @override diff --git a/lib/src/component_server.dart b/lib/src/component_server.dart index 3a154ea..6be602a 100644 --- a/lib/src/component_server.dart +++ b/lib/src/component_server.dart @@ -14,11 +14,12 @@ library w_flux.src.component_server; +import 'package:w_flux/src/action.dart'; import 'package:w_flux/src/component_common.dart'; import 'package:w_flux/src/store.dart'; /// FluxComponents are responsible for rendering application views and turning -/// user interactions and events into [Action]s. FluxComponents can use data +/// user interactions and events into [ActionV2]s. FluxComponents can use data /// from one or many [Store] instances to define the resulting component. /// /// This FluxComponent, intended for use on the server, does not depend on diff --git a/lib/src/mixins/batched_redraws.dart b/lib/src/mixins/batched_redraws.dart index 7479c33..365bc6e 100644 --- a/lib/src/mixins/batched_redraws.dart +++ b/lib/src/mixins/batched_redraws.dart @@ -1,3 +1,5 @@ +// ignore_for_file: deprecated_member_use + library w_flux.mixins.batched_redraws; import 'dart:async'; @@ -5,11 +7,12 @@ import 'dart:html'; import 'package:react/react.dart' as react; -class _RedrawScheduler implements Function { - Map> _components = - >{}; +import 'package:w_flux/src/component_client.dart'; + +class _RedrawScheduler { + final _components = >{}; - void call(BatchedRedraws component, [callback()?]) { + void call(BatchedRedraws component, [Function()? callback]) { if (_components.isEmpty) { _tick(); } @@ -23,11 +26,11 @@ class _RedrawScheduler implements Function { await window.animationFrame; // Making a copy of `_components` so we don't iterate over the map while it's potentially being mutated. - var entries = _components.entries.toList(); + final entries = _components.entries.toList(); _components.clear(); - for (var entry in entries) { - var component = entry.key; - var callbacks = entry.value; + for (final entry in entries) { + final component = entry.key; + final callbacks = entry.value; // Skip if the component doesn't want to batch redraw if (!component.shouldBatchRedraw) { continue; @@ -37,9 +40,9 @@ class _RedrawScheduler implements Function { if (callbacks.isNotEmpty) { chainedCallbacks = () { - callbacks.forEach((callback) { + for (final callback in callbacks) { callback(); - }); + } }; } @@ -53,8 +56,8 @@ class _RedrawScheduler implements Function { _RedrawScheduler _scheduleRedraw = _RedrawScheduler(); -/// A mixin that overrides the [Component.redraw] method of a React -/// [Component] (including a [FluxComponent]) and prevents the component +/// A mixin that overrides the [react.Component.redraw] method of a React +/// [react.Component] (including a [FluxComponent]) and prevents the component /// from being redrawn more than once per animation frame. /// /// Example: @@ -67,5 +70,5 @@ _RedrawScheduler _scheduleRedraw = _RedrawScheduler(); class BatchedRedraws { bool shouldBatchRedraw = true; - void redraw([callback()?]) => _scheduleRedraw(this, callback); + void redraw([Function()? callback]) => _scheduleRedraw(this, callback); } diff --git a/lib/src/store.dart b/lib/src/store.dart index a715a74..faa5953 100644 --- a/lib/src/store.dart +++ b/lib/src/store.dart @@ -36,9 +36,10 @@ typedef StoreHandler = Function(Store event); /// listened to. Whenever a `Store`'s data is mutated, the `trigger` method is /// used to tell all registered listeners that updated data is available. /// -/// In a typical application using `w_flux`, a [FluxComponent] listens to +/// In a typical application using `w_flux`, a `FluxComponent` listens to /// `Store`s, triggering re-rendering of the UI elements based on the updated /// `Store` data. +// ignore: prefer_mixin class Store extends Stream with Disposable { @override String get disposableTypeName => 'Store'; @@ -96,7 +97,7 @@ class Store extends Stream with Disposable { /// needed. @override StreamSubscription listen(StoreHandler? onData, - {Function? onError, void onDone()?, bool? cancelOnError}) { + {Function? onError, void Function()? onDone, bool? cancelOnError}) { if (isDisposed) { throw StateError('Store of type $runtimeType has been disposed'); } @@ -141,8 +142,9 @@ class Store extends Stream with Disposable { /// If the `Store` has been disposed, this method throws a [StateError]. /// Deprecated: 2.9.5 /// To be removed: 3.0.0 - @deprecated - triggerOnAction(ActionV2 action, [void onAction(payload)?]) { + @Deprecated('Use triggerOnActionV2 instead') + // ignore: always_declare_return_types, type_annotate_public_apis + triggerOnAction(ActionV2 action, [void Function(dynamic payload)? onAction]) { triggerOnActionV2(action, onAction); } @@ -155,7 +157,7 @@ class Store extends Stream with Disposable { /// /// If the `Store` has been disposed, this method throws a [StateError]. void triggerOnActionV2(ActionV2 action, - [FutureOr onAction(T payload)?]) { + [FutureOr Function(T payload)? onAction]) { if (isOrWillBeDisposed) { throw StateError('Store of type $runtimeType has been disposed'); } diff --git a/lib/w_flux.dart b/lib/w_flux.dart index 48c04a2..63e008c 100644 --- a/lib/w_flux.dart +++ b/lib/w_flux.dart @@ -13,15 +13,19 @@ // limitations under the License. /// The w_flux library implements a uni-directional data flow pattern comprised -/// of [Action]s, [Store]s, and [FluxComponent]s. +/// of [ActionV2]s, [Store]s, and [FluxComponent]s. /// -/// - [Action]s initiate mutation of app data that resides in [Store]s. +/// - [ActionV2]s initiate mutation of app data that resides in [Store]s. /// - Data mutations within [Store]s trigger re-rendering of app view (defined /// in [FluxComponent]s). -/// - [FluxComponent]s dispatch [Action]s in response to user interaction. +/// - [FluxComponent]s dispatch [ActionV2]s in response to user interaction. library w_flux; +import 'src/action.dart'; +import 'src/component_client.dart'; +import 'src/store.dart'; + export 'src/action.dart'; export 'src/component_client.dart'; -export 'src/store.dart'; export 'src/mixins/batched_redraws.dart'; +export 'src/store.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 9b78050..cc1ec97 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ description: Flux library for uni-directional dataflow inspired by reflux and Fa homepage: https://github.com/Workiva/w_flux environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.19.0 <4.0.0' dependencies: meta: ^1.6.0 @@ -16,6 +16,7 @@ dev_dependencies: build_runner: ^2.0.0 build_test: ^2.1.3 build_web_compilers: ^3.0.0 - dart_dev: ^4.0.0 + dart_dev: ^4.1.0 dependency_validator: ^3.0.0 - test: ^1.18.2 + test: ^1.18.2 + workiva_analysis_options: ^1.4.1 diff --git a/test/action_test.dart b/test/action_test.dart index 64bdfb5..7c070a7 100644 --- a/test/action_test.dart +++ b/test/action_test.dart @@ -12,13 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +// ignore_for_file: deprecated_member_use_from_same_package + @TestOn('browser') library w_flux.test.action_test; import 'dart:async'; -import 'package:w_flux/src/action.dart'; import 'package:test/test.dart'; +import 'package:w_flux/src/action.dart'; void main() { group('Action', () { @@ -30,14 +32,14 @@ void main() { }); test('should only be equivalent to itself', () { - Action action = Action(); - Action actionV2 = Action(); + final action = Action(); + final actionV2 = Action(); expect(action == action, isTrue); expect(action == actionV2, isFalse); }); test('should support dispatch without a payload', () async { - Action action = Action() + final action = Action() ..listen(expectAsync1((payload) { expect(payload, isNull); })); @@ -47,7 +49,7 @@ void main() { test('should support dispatch by default when called with a payload', () async { - action.listen(expectAsync1((String? payload) { + action.listen(expectAsync1((payload) { expect(payload, equals('990 guerrero')); })); @@ -59,7 +61,7 @@ void main() { 'should invoke and complete synchronous listeners in future event in ' 'event queue', () async { var listenerCompleted = false; - var action = Action() + final action = Action() ..listen((_) { listenerCompleted = true; }); @@ -76,7 +78,7 @@ void main() { test( 'should invoke asynchronous listeners in future event and complete ' 'in another future event', () async { - var action = Action(); + final action = Action(); var listenerInvoked = false; var listenerCompleted = false; action.listen((_) async { @@ -99,7 +101,7 @@ void main() { }); test('should complete future after listeners complete', () async { - var action = Action(); + final action = Action(); var asyncListenerCompleted = false; action.listen((_) async { await Future.delayed(Duration(milliseconds: 100), () { @@ -107,7 +109,7 @@ void main() { }); }); - Future? future = action(); + final future = action(); expect(asyncListenerCompleted, isFalse); await future; @@ -115,16 +117,16 @@ void main() { }); test('should surface errors in listeners', () { - var action = Action()..listen((_) => throw UnimplementedError()); + final action = Action()..listen((_) => throw UnimplementedError()); expect(action(0), throwsUnimplementedError); }); }); group('listen', () { test('should stop listening when subscription is canceled', () async { - var action = Action(); + final action = Action(); var listened = false; - var subscription = action.listen((_) => listened = true); + final subscription = action.listen((_) => listened = true); await action(); expect(listened, isTrue); @@ -136,7 +138,7 @@ void main() { }); test('should stop listening when listeners are cleared', () async { - var action = Action(); + final action = Action(); var listened = false; action.listen((_) => listened = true); @@ -150,7 +152,7 @@ void main() { }); test('should stop listening when actions are disposed', () async { - var action = Action(); + final action = Action(); var listened = false; action.listen((_) => listened = true); @@ -166,10 +168,10 @@ void main() { group('benchmarks', () { test('should dispatch actions faster than streams :(', () async { - const int sampleSize = 1000; - var stopwatch = Stopwatch(); + const sampleSize = 1000; + final stopwatch = Stopwatch(); - var awaitableAction = Action() + final awaitableAction = Action() ..listen((_) => {}) ..listen((_) async {}); stopwatch.start(); @@ -177,14 +179,14 @@ void main() { await awaitableAction(); } stopwatch.stop(); - var averageActionDispatchTime = + final averageActionDispatchTime = stopwatch.elapsedMicroseconds / sampleSize / 1000.0; stopwatch.reset(); late Completer syncCompleter; late Completer asyncCompleter; - var action = Action() + final action = Action() ..listen((_) => syncCompleter.complete()) ..listen((_) async { asyncCompleter.complete(); @@ -197,7 +199,7 @@ void main() { await Future.wait([syncCompleter.future, asyncCompleter.future]); } stopwatch.stop(); - var averageStreamDispatchTime = + final averageStreamDispatchTime = stopwatch.elapsedMicroseconds / sampleSize / 1000.0; print('awaitable action (ms): $averageActionDispatchTime; ' @@ -215,8 +217,8 @@ void main() { }); test('should only be equivalent to itself', () { - ActionV2 action = ActionV2(); - ActionV2 actionV2 = ActionV2(); + final action = ActionV2(); + final actionV2 = ActionV2(); expect(action == action, isTrue); expect(action == actionV2, isFalse); }); @@ -280,7 +282,7 @@ void main() { }); }); - Future? future = action('payload'); + final future = action('payload'); expect(asyncListenerCompleted, isFalse); await future; @@ -296,7 +298,7 @@ void main() { group('listen', () { test('should stop listening when subscription is canceled', () async { var listened = false; - var subscription = action.listen((_) => listened = true); + final subscription = action.listen((_) => listened = true); await action('payload'); expect(listened, isTrue); @@ -336,10 +338,10 @@ void main() { group('benchmarks', () { test('should dispatch actions faster than streams :(', () async { - const int sampleSize = 1000; - var stopwatch = Stopwatch(); + const sampleSize = 1000; + final stopwatch = Stopwatch(); - var awaitableAction = ActionV2() + final awaitableAction = ActionV2() ..listen((_) => {}) ..listen((_) async {}); stopwatch.start(); @@ -347,14 +349,14 @@ void main() { await awaitableAction(null); } stopwatch.stop(); - var averageActionDispatchTime = + final averageActionDispatchTime = stopwatch.elapsedMicroseconds / sampleSize / 1000.0; stopwatch.reset(); late Completer syncCompleter; late Completer asyncCompleter; - var action = ActionV2() + final action = ActionV2() ..listen((_) => syncCompleter.complete()) ..listen((_) async { asyncCompleter.complete(); @@ -367,7 +369,7 @@ void main() { await Future.wait([syncCompleter.future, asyncCompleter.future]); } stopwatch.stop(); - var averageStreamDispatchTime = + final averageStreamDispatchTime = stopwatch.elapsedMicroseconds / sampleSize / 1000.0; print('awaitable action (ms): $averageActionDispatchTime; ' @@ -377,9 +379,11 @@ void main() { }); group('Null typed', () { + // ignore: prefer_void_to_null late ActionV2 nullAction; setUp(() { + // ignore: prefer_void_to_null nullAction = ActionV2(); addTearDown(nullAction.dispose); }); diff --git a/test/component_server_test.dart b/test/component_server_test.dart index b1a0a30..ddd2ecf 100644 --- a/test/component_server_test.dart +++ b/test/component_server_test.dart @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// ignore_for_file: always_declare_return_types, type_annotate_public_apis + @TestOn('browser') library w_flux.test.component_server_test; @@ -26,16 +28,16 @@ import 'utils.dart'; void main() { group('FluxComponent', () { test('should expose an actions getter', () { - TestDefaultComponent component = TestDefaultComponent(); - TestActions testActions = TestActions(); + final component = TestDefaultComponent(); + final testActions = TestActions(); component.props = {'actions': testActions}; expect(component.actions, equals(testActions)); }); test('should expose a store getter', () { - TestDefaultComponent component = TestDefaultComponent(); - TestStore testStore = TestStore(); + final component = TestDefaultComponent(); + final testStore = TestStore(); component.props = {'store': testStore}; expect(component.store, equals(testStore)); @@ -43,8 +45,8 @@ void main() { test('should subscribe to a single store by default', () async { // Setup the component - TestDefaultComponent component = TestDefaultComponent(); - TestStore store = TestStore(); + final component = TestDefaultComponent(); + final store = TestStore(); component.props = {'store': store}; component.componentWillMount(); @@ -66,8 +68,8 @@ void main() { }); test('should subscribe to any stores returned in redrawOn', () async { - TestRedrawOnComponent component = TestRedrawOnComponent(); - TestStores stores = TestStores(); + final component = TestRedrawOnComponent(); + final stores = TestStores(); component.props = {'store': stores}; component.componentWillMount(); @@ -86,8 +88,8 @@ void main() { test('should prefer a handler specified in getStoreHandlers over redrawOn', () async { - TestHandlerPrecedence component = TestHandlerPrecedence(); - TestStores stores = TestStores(); + final component = TestHandlerPrecedence(); + final stores = TestStores(); component.props = {'store': stores}; component.componentWillMount(); @@ -104,8 +106,8 @@ void main() { test('should not attempt subscription if store is a composite of stores', () async { - TestDefaultComponent component = TestDefaultComponent(); - TestStores stores = TestStores(); + final component = TestDefaultComponent(); + final stores = TestStores(); component.props = {'store': stores}; component.componentWillMount(); @@ -122,8 +124,8 @@ void main() { 'should call handlers specified in getStoreHandlers when each store triggers', () async { // Setup the component - TestStoreHandlersComponent component = TestStoreHandlersComponent(); - TestStore store = TestStore(); + final component = TestStoreHandlersComponent(); + final store = TestStore(); component.props = {'store': store}; component.componentWillMount(); @@ -147,11 +149,11 @@ void main() { test('should cancel any subscriptions added with addSubscription', () async { // Setup a new subscription on a component - int numberOfCalls = 0; - StreamController controller = StreamController(); - TestDefaultComponent component = TestDefaultComponent(); + var numberOfCalls = 0; + final controller = StreamController(); + final component = TestDefaultComponent(); - var subscription = controller.stream.listen((_) { + final subscription = controller.stream.listen((_) { numberOfCalls += 1; }); component.getManagedDisposer(() async => subscription.cancel()); @@ -186,9 +188,11 @@ class TestStores { class TestDefaultComponent extends FluxComponent { int numberOfRedraws = 0; + @override render() => react.div({}); - redraw([callback()?]) { + @override + redraw([Function()? callback]) { numberOfRedraws += 1; } } @@ -196,8 +200,10 @@ class TestDefaultComponent extends FluxComponent { class TestStoreHandlersComponent extends FluxComponent { int numberOfHandlerCalls = 0; + @override render() => react.div({}); + @override getStoreHandlers() => {store: increment}; increment(Store _) { @@ -208,11 +214,14 @@ class TestStoreHandlersComponent extends FluxComponent { class TestRedrawOnComponent extends FluxComponent { int numberOfRedraws = 0; + @override render() => react.div({}); + @override redrawOn() => [store.store1, store.store2]; - redraw([callback()?]) { + @override + redraw([Function()? callback]) { numberOfRedraws += 1; } } @@ -221,17 +230,21 @@ class TestHandlerPrecedence extends FluxComponent { int numberOfRedraws = 0; int numberOfHandlerCalls = 0; + @override render() => react.div({}); + @override redrawOn() => [store.store1, store.store2]; + @override getStoreHandlers() => {store.store1: increment}; increment(Store _) { numberOfHandlerCalls += 1; } - redraw([callback()?]) { + @override + redraw([Function()? callback]) { numberOfRedraws += 1; } } diff --git a/test/component_test.dart b/test/component_test.dart index 7bfa609..7057490 100644 --- a/test/component_test.dart +++ b/test/component_test.dart @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// ignore_for_file: always_declare_return_types, type_annotate_public_apis + @TestOn('browser') library w_flux.test.component_test; @@ -25,16 +27,16 @@ import 'package:w_flux/w_flux.dart'; void main() { group('FluxComponent', () { test('should expose an actions getter', () { - TestDefaultComponent component = TestDefaultComponent(); - TestActions testActions = TestActions(); + final component = TestDefaultComponent(); + final testActions = TestActions(); component.props = {'actions': testActions}; expect(component.actions, equals(testActions)); }); test('should expose a store getter', () { - TestDefaultComponent component = TestDefaultComponent(); - TestStore testStore = TestStore(); + final component = TestDefaultComponent(); + final testStore = TestStore(); component.props = {'store': testStore}; expect(component.store, equals(testStore)); @@ -42,8 +44,8 @@ void main() { test('should subscribe to a single store by default', () async { // Setup the component - TestDefaultComponent component = TestDefaultComponent(); - TestStore store = TestStore(); + final component = TestDefaultComponent(); + final store = TestStore(); component.props = {'store': store}; component.componentWillMount(); @@ -65,8 +67,8 @@ void main() { }); test('should subscribe to any stores returned in redrawOn', () async { - TestRedrawOnComponent component = TestRedrawOnComponent(); - TestStores stores = TestStores(); + final component = TestRedrawOnComponent(); + final stores = TestStores(); component.props = {'store': stores}; component.componentWillMount(); @@ -85,8 +87,8 @@ void main() { test('should prefer a handler specified in getStoreHandlers over redrawOn', () async { - TestHandlerPrecedence component = TestHandlerPrecedence(); - TestStores stores = TestStores(); + final component = TestHandlerPrecedence(); + final stores = TestStores(); component.props = {'store': stores}; component.componentWillMount(); @@ -103,8 +105,8 @@ void main() { test('should not attempt subscription if store is a composite of stores', () async { - TestDefaultComponent component = TestDefaultComponent(); - TestStores stores = TestStores(); + final component = TestDefaultComponent(); + final stores = TestStores(); component.props = {'store': stores}; component.componentWillMount(); @@ -121,8 +123,8 @@ void main() { 'should call handlers specified in getStoreHandlers when each store triggers', () async { // Setup the component - TestStoreHandlersComponent component = TestStoreHandlersComponent(); - TestStore store = TestStore(); + final component = TestStoreHandlersComponent(); + final store = TestStore(); component.props = {'store': store}; component.componentWillMount(); @@ -166,10 +168,10 @@ void main() { test('should cancel any subscriptions added with addSubscription', () async { // Setup a new subscription on a component - int numberOfCalls = 0; - StreamController controller = StreamController(); - TestDefaultComponent component = TestDefaultComponent(); - var subscription = controller.stream.listen((_) { + var numberOfCalls = 0; + final controller = StreamController(); + final component = TestDefaultComponent(); + final subscription = controller.stream.listen((_) { numberOfCalls += 1; }); component.getManagedDisposer(() async => subscription.cancel()); @@ -190,7 +192,7 @@ void main() { }); test('should not redraw after being unmounted', () async { - TestDefaultComponent component = TestDefaultComponent(); + final component = TestDefaultComponent(); component.componentWillUnmount(); await component.didDispose; component.redraw(); @@ -201,7 +203,7 @@ void main() { } Future animationFrames([int numFrames = 1]) async { - for (int i = 0; i < numFrames; i++) { + for (var i = 0; i < numFrames; i++) { await window.animationFrame; } } @@ -219,9 +221,11 @@ class TestStores { class TestDefaultComponent extends FluxComponent { int numberOfRedraws = 0; + @override render() => react.div({}); - void setState(_, [callback()?]) { + @override + void setState(_, [Function()? callback]) { numberOfRedraws++; if (callback != null) callback(); } @@ -230,8 +234,10 @@ class TestDefaultComponent extends FluxComponent { class TestStoreHandlersComponent extends FluxComponent { int numberOfHandlerCalls = 0; + @override render() => react.div({}); + @override getStoreHandlers() => {store: increment}; increment(Store _) { @@ -242,11 +248,14 @@ class TestStoreHandlersComponent extends FluxComponent { class TestRedrawOnComponent extends FluxComponent { int numberOfRedraws = 0; + @override render() => react.div({}); + @override redrawOn() => [store.store1, store.store2]; - void setState(_, [callback()?]) { + @override + void setState(_, [Function()? callback]) { numberOfRedraws++; if (callback != null) callback(); } @@ -256,17 +265,21 @@ class TestHandlerPrecedence extends FluxComponent { int numberOfRedraws = 0; int numberOfHandlerCalls = 0; + @override render() => react.div({}); + @override redrawOn() => [store.store1, store.store2]; + @override getStoreHandlers() => {store.store1: increment}; increment(Store _) { numberOfHandlerCalls += 1; } - void setState(_, [callback()?]) { + @override + void setState(_, [Function()? callback]) { numberOfRedraws++; if (callback != null) callback(); } @@ -276,9 +289,11 @@ class TestHandlerLifecycle extends FluxComponent { int numberOfRedraws = 0; List> lifecycleCalls = []; + @override render() => react.div({}); - void setState(_, [callback()?]) { + @override + void setState(_, [Function()? callback]) { numberOfRedraws++; if (callback != null) callback(); } diff --git a/test/mixins/batched_redraws_test.dart b/test/mixins/batched_redraws_test.dart index 08d44a5..3027605 100644 --- a/test/mixins/batched_redraws_test.dart +++ b/test/mixins/batched_redraws_test.dart @@ -20,15 +20,18 @@ import 'dart:html'; import 'package:react/react.dart' as react; -import 'package:w_flux/w_flux.dart'; import 'package:test/test.dart'; +import 'package:w_flux/w_flux.dart'; +// ignore: deprecated_member_use, prefer_mixin class _TestComponent extends react.Component with BatchedRedraws { int renderCount = 0; + @override dynamic render() => ''; - void setState(_, [callback()?]) { + @override + void setState(_, [Function()? callback]) { renderCount++; if (callback != null) callback(); } diff --git a/test/store_test.dart b/test/store_test.dart index 4990b13..e956566 100644 --- a/test/store_test.dart +++ b/test/store_test.dart @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// ignore_for_file: deprecated_member_use_from_same_package, always_declare_return_types, type_annotate_public_apis + @TestOn('browser') library w_flux.test.store_test; @@ -34,9 +36,9 @@ class MockTransformer implements StreamTransformer { Stream bind(Stream stream) => _buildTransformer().bind(stream); static StreamTransformer _buildTransformer() { - int count = 0; + var count = 0; return StreamTransformer.fromHandlers( - handleData: (Store data, EventSink sink) { + handleData: (data, sink) { if (count < 2) { count++; sink.add(data); @@ -76,7 +78,7 @@ void main() { test('should trigger with itself as the payload', () { store.listen(expectAsync1((payload) { expect(payload, store); - }) as StoreHandler); + })); store.trigger(); }); @@ -85,7 +87,7 @@ void main() { // ensure that multiple trigger executions emit // exactly 2 throttled triggers to external listeners store = Store.withTransformer(MockTransformer()); - store.listen(expectAsync1((payload) {}, count: 2) as StoreHandler); + store.listen(expectAsync1((payload) {}, count: 2)); store.trigger(); store.trigger(); @@ -94,11 +96,11 @@ void main() { }); test('should trigger in response to an action', () async { - Action _action = Action(); + final _action = Action(); store.triggerOnActionV2(_action); - _action(); - Store payload = await store.first; + unawaited(_action()); + final payload = await store.first; expect(payload, store); }); @@ -106,8 +108,8 @@ void main() { test( 'should execute a given method and then trigger in response to an action', () { - Action _action = Action(); - bool methodCalled = false; + final _action = Action(); + var methodCalled = false; syncCallback(_) { methodCalled = true; } @@ -116,15 +118,15 @@ void main() { store.listen(expectAsync1((payload) { expect(payload, store); expect(methodCalled, isTrue); - }) as StoreHandler); + })); _action(); }); test( 'should execute a given async method and then trigger in response to an action', () { - Action _action = Action(); - bool afterTimer = false; + final _action = Action(); + var afterTimer = false; asyncCallback(_) async { await Future.delayed(Duration(milliseconds: 30)); afterTimer = true; @@ -134,25 +136,25 @@ void main() { store.listen(expectAsync1((payload) { expect(payload, store); expect(afterTimer, isTrue); - }) as StoreHandler); + })); _action(); }); test( 'should execute a given method and then trigger in response to an action with payload', () { - Action _action = Action(); + final _action = Action(); num? counter = 0; - store.triggerOnActionV2(_action, (num? payload) => counter = payload); + store.triggerOnActionV2(_action, (payload) => counter = payload); store.listen(expectAsync1((payload) { expect(payload, store); expect(counter, 17); - }) as StoreHandler); + })); _action(17); }); test('cleans up its StreamController on dispose', () { - bool afterDispose = false; + var afterDispose = false; store.listen(expectAsync1((payload) async { // Safety check to avoid infinite trigger loop @@ -164,15 +166,15 @@ void main() { // This should no longer fire after dispose store.trigger(); - }) as StoreHandler); + })); store.trigger(); }); test('cleans up its ActionSubscriptions on dispose', () { - bool afterDispose = false; + var afterDispose = false; - Action _action = Action(); + final _action = Action(); store.triggerOnActionV2(_action); store.listen(expectAsync1((payload) async { // Safety check to avoid infinite trigger loop @@ -183,8 +185,8 @@ void main() { afterDispose = true; // This should no longer fire after dispose - _action(); - }) as StoreHandler); + unawaited(_action()); + })); _action(); });