Repository: flutter/flutter
File: packages/flutter/test/widgets/form_test.dart (Dart)

Code before:
                ),
                DropdownButtonFormField<String>(
                  key: const ValueKey('animal'),
                  initialValue: 'cat',
                  items: const [
                    DropdownMenuItem(value: 'dog', child: SizedBox.shrink()),
                    DropdownMenuItem(value: 'cat', child: SizedBox.shrink()),
                    DropdownMenuItem(value: 'bird', child: SizedBox.shrink()),
                  ],
                  onChanged: (_) {},
                ),
              ],
            ),
          ),
        ),
      ),
    );

    Map<String, dynamic> collectData() {
      return {
        for (final field in formKey.currentState!.fields)
          if (field.widget.key case ValueKey<String>(:final value)) value: field.value,
      };
    }

    expect(collectData(), {'name': 'Name', 'email': 'Email', 'age': 18, 'animal': 'cat'});

    FormFieldState<T> field<T>(String key) => formKey.currentState!.fields
        .whereType<FormFieldState<T>>()
        .singleWhere((f) => f.widget.key == ValueKey(key));

    field<String>('name').didChange('New Name');
    field<String>('email').didChange('new@email.com');
    field<int>('age').didChange(30);
    field<String>('animal').didChange('dog');

    await tester.pump();

    expect(collectData(), {
      'name': 'New Name',
      'email': 'new@email.com',
      'age': 30,
      'animal': 'dog',
    });
  });
}

class _PlatformAnnounceScenario {
  _PlatformAnnounceScenario({required this.supportsAnnounce, required this.testName});
  final bool supportsAnnounce;
  final String testName;

Review comment (suggestion):
Per Flutter's style guide, please explicitly type map literals: https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md#avoid-using-var-and-dynamic

Something like:

```suggestion
    expect(collectData(), <String, Object>{'name': 'Name', 'email': 'Email', 'age': 18, 'animal': 'cat'});
```

Same comment below for line 1972.

Code after:

    expect(formState.fields.length, equals(2));
    expect(formState.fields.map((field) => field.value), containsAll(<String>['A', 'B']));
  });

  testWidgets('reports all fields as invalid after validation errors', (WidgetTester tester) async {
    final formKey = GlobalKey<FormState>();
    String errorText(String? value) => '$value/error';

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Form(
            key: formKey,
            child: Column(
              children: <Widget>[
                TextFormField(initialValue: 'foo', validator: errorText),
                TextFormField(initialValue: 'bar', validator: errorText),
              ],
            ),
          ),
        ),
      ),
    );

    formKey.currentState?.validate();
    await tester.pump();

    expect(find.text(errorText('foo')), findsOneWidget);
    expect(find.text(errorText('bar')), findsOneWidget);

    final List<FormFieldState<dynamic>> fields = formKey.currentState!.fields.toList();

    // Expect all fields to be invalid.
    expect(fields.every((field) => !field.isValid), isTrue);
  });

  testWidgets('isValid evaluates validity without updating error UI', (WidgetTester tester) async {
    final formKey = GlobalKey<FormState>();
    String errorText(String? value) => '$value/error';

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Form(
            key: formKey,
            child: TextFormField(initialValue: 'foo', validator: errorText),
          ),
        ),
      ),
    );