diff --git a/packages/flutter/lib/src/foundation/licenses.dart b/packages/flutter/lib/src/foundation/licenses.dart index cf44f8bb81..0844b626ac 100644 --- a/packages/flutter/lib/src/foundation/licenses.dart +++ b/packages/flutter/lib/src/foundation/licenses.dart @@ -4,6 +4,8 @@ import 'dart:async'; +import 'package:meta/meta.dart' show visibleForTesting; + /// Signature for callbacks passed to [LicenseRegistry.addLicense]. typedef LicenseEntryCollector = Stream Function(); @@ -306,4 +308,11 @@ class LicenseRegistry { for (LicenseEntryCollector collector in _collectors) yield* collector(); } + + /// Resets the internal state of [LicenseRegistry]. Intended for use in + /// testing. + @visibleForTesting + static void reset() { + _collectors = null; + } } diff --git a/packages/flutter/test/material/about_test.dart b/packages/flutter/test/material/about_test.dart index 172d0928cb..3d30da0834 100644 --- a/packages/flutter/test/material/about_test.dart +++ b/packages/flutter/test/material/about_test.dart @@ -9,6 +9,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { + tearDown(() { + LicenseRegistry.reset(); + }); + testWidgets('AboutListTile control test', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( @@ -131,6 +135,72 @@ void main() { await tester.pumpAndSettle(); - expect(tester.getTopLeft(find.text('DEF')), const Offset(8.0 + safeareaPadding, 527.0)); + expect(tester.getTopLeft(find.text('DEF')), const Offset(8.0 + safeareaPadding, 287.0)); + }, skip: isBrowser); + + testWidgets('LicensePage returns early if unmounted', (WidgetTester tester) async { + final Completer licenseCompleter = Completer(); + LicenseRegistry.addLicense(() { + return Stream.fromFuture(licenseCompleter.future); + }); + + await tester.pumpWidget( + const MaterialApp( + home: LicensePage(), + ), + ); + await tester.pump(); + + await tester.pumpWidget( + const MaterialApp( + home: Placeholder(), + ), + ); + + await tester.pumpAndSettle(); + final FakeLicenseEntry licenseEntry = FakeLicenseEntry(); + licenseCompleter.complete(licenseEntry); + expect(licenseEntry.paragraphsCalled, false); + }, skip: isBrowser); + + testWidgets('LicensePage returns late if unmounted', (WidgetTester tester) async { + final Completer licenseCompleter = Completer(); + LicenseRegistry.addLicense(() { + return Stream.fromFuture(licenseCompleter.future); + }); + + await tester.pumpWidget( + const MaterialApp( + home: LicensePage(), + ), + ); + await tester.pump(); + final FakeLicenseEntry licenseEntry = FakeLicenseEntry(); + licenseCompleter.complete(licenseEntry); + + await tester.pumpWidget( + const MaterialApp( + home: Placeholder(), + ), + ); + + await tester.pumpAndSettle(); + expect(licenseEntry.paragraphsCalled, true); }, skip: isBrowser); } + +class FakeLicenseEntry extends LicenseEntry { + FakeLicenseEntry(); + + bool get paragraphsCalled => _paragraphsCalled; + bool _paragraphsCalled = false; + + @override + Iterable packages = []; + + @override + Iterable get paragraphs { + _paragraphsCalled = true; + return []; + } +}