[url_launcher_web] Migrate to null-safety (#3522)
This version uses auto-generated Mocks from mockito5 for its tests.
For now, tests only run in the `master` channel.
Co-authored-by: Maurits van Beusekom <maurits@baseflow.com>
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 47cdbd2..2b62a6a 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -4,6 +4,7 @@
# Ignore generated files
- '**/*.g.dart'
- 'lib/src/generated/*.dart'
+ - '**/*.mocks.dart' # Mockito @GenerateMocks
errors:
always_require_non_null_named_parameters: false # not needed with nnbd
unnecessary_null_comparison: false # Turned as long as nnbd mix-mode is supported.
diff --git a/packages/url_launcher/url_launcher_web/CHANGELOG.md b/packages/url_launcher/url_launcher_web/CHANGELOG.md
index 0416c03..49d7245 100644
--- a/packages/url_launcher/url_launcher_web/CHANGELOG.md
+++ b/packages/url_launcher/url_launcher_web/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 2.0.0-nullsafety
+
+- Migrate to null safety.
+
# 0.1.5+3
- Fix Link misalignment [issue](https://github.com/flutter/flutter/issues/70053).
diff --git a/packages/url_launcher/url_launcher_web/example/README.md b/packages/url_launcher/url_launcher_web/example/README.md
new file mode 100644
index 0000000..b75df09
--- /dev/null
+++ b/packages/url_launcher/url_launcher_web/example/README.md
@@ -0,0 +1,31 @@
+# Testing
+
+This package utilizes the `integration_test` package to run its tests in a web browser.
+
+See [flutter.dev > Integration testing](https://flutter.dev/docs/testing/integration-tests) for more info.
+
+## Running the tests
+
+Make sure you have updated to the latest Flutter master.
+
+1. Check what version of Chrome is running on the machine you're running tests on.
+
+2. Download and install driver for that version from here:
+ * <https://chromedriver.chromium.org/downloads>
+
+3. Start the driver using `chromedriver --port=4444`
+
+4. Run tests: `flutter drive -d web-server --browser-name=chrome --driver=test_driver/integration_test_driver.dart --target=integration_test/TEST_NAME.dart`, or (in Linux):
+
+ * Single: `./run_test.sh integration_test/TEST_NAME.dart`
+ * All: `./run_test.sh`
+
+## Mocks
+
+There's `.mocks.dart` files next to the test files that use them.
+
+They're [generated by Mockito](https://github.com/dart-lang/mockito/blob/master/NULL_SAFETY_README.md#code-generation).
+
+Mocks might be manually re-generated with the following command: `flutter pub run build_runner build`. If there are any changes in the mocks, feel free to commit them.
+
+(Mocks will be auto-generated by the `run_test.sh` script as well.)
diff --git a/packages/url_launcher/url_launcher_web/example/build.yaml b/packages/url_launcher/url_launcher_web/example/build.yaml
new file mode 100644
index 0000000..db3104b
--- /dev/null
+++ b/packages/url_launcher/url_launcher_web/example/build.yaml
@@ -0,0 +1,6 @@
+targets:
+ $default:
+ sources:
+ - integration_test/*.dart
+ - lib/$lib$
+ - $package$
diff --git a/packages/url_launcher/url_launcher_web/example/integration_test/link_widget_test.dart b/packages/url_launcher/url_launcher_web/example/integration_test/link_widget_test.dart
new file mode 100644
index 0000000..3c1dbd8
--- /dev/null
+++ b/packages/url_launcher/url_launcher_web/example/integration_test/link_widget_test.dart
@@ -0,0 +1,150 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:html' as html;
+import 'dart:js_util';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:url_launcher_platform_interface/link.dart';
+import 'package:url_launcher_web/src/link.dart';
+import 'package:integration_test/integration_test.dart';
+
+void main() {
+ IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+
+ group('Link Widget', () {
+ testWidgets('creates anchor with correct attributes',
+ (WidgetTester tester) async {
+ final Uri uri = Uri.parse('http://foobar/example?q=1');
+ await tester.pumpWidget(Directionality(
+ textDirection: TextDirection.ltr,
+ child: WebLinkDelegate(TestLinkInfo(
+ uri: uri,
+ target: LinkTarget.blank,
+ builder: (BuildContext context, FollowLink? followLink) {
+ return Container(width: 100, height: 100);
+ },
+ )),
+ ));
+ // Platform view creation happens asynchronously.
+ await tester.pumpAndSettle();
+
+ final html.Element anchor = _findSingleAnchor();
+ expect(anchor.getAttribute('href'), uri.toString());
+ expect(anchor.getAttribute('target'), '_blank');
+
+ final Uri uri2 = Uri.parse('http://foobar2/example?q=2');
+ await tester.pumpWidget(Directionality(
+ textDirection: TextDirection.ltr,
+ child: WebLinkDelegate(TestLinkInfo(
+ uri: uri2,
+ target: LinkTarget.self,
+ builder: (BuildContext context, FollowLink? followLink) {
+ return Container(width: 100, height: 100);
+ },
+ )),
+ ));
+ await tester.pumpAndSettle();
+
+ // Check that the same anchor has been updated.
+ expect(anchor.getAttribute('href'), uri2.toString());
+ expect(anchor.getAttribute('target'), '_self');
+ });
+
+ testWidgets('sizes itself correctly', (WidgetTester tester) async {
+ final Key containerKey = GlobalKey();
+ final Uri uri = Uri.parse('http://foobar');
+ await tester.pumpWidget(Directionality(
+ textDirection: TextDirection.ltr,
+ child: Center(
+ child: ConstrainedBox(
+ constraints: BoxConstraints.tight(Size(100.0, 100.0)),
+ child: WebLinkDelegate(TestLinkInfo(
+ uri: uri,
+ target: LinkTarget.blank,
+ builder: (BuildContext context, FollowLink? followLink) {
+ return Container(
+ key: containerKey,
+ child: SizedBox(width: 50.0, height: 50.0),
+ );
+ },
+ )),
+ ),
+ ),
+ ));
+ await tester.pumpAndSettle();
+
+ final Size containerSize = tester.getSize(find.byKey(containerKey));
+ // The Stack widget inserted by the `WebLinkDelegate` shouldn't loosen the
+ // constraints before passing them to the inner container. So the inner
+ // container should respect the tight constraints given by the ancestor
+ // `ConstrainedBox` widget.
+ expect(containerSize.width, 100.0);
+ expect(containerSize.height, 100.0);
+ });
+
+ // See: https://github.com/flutter/plugins/pull/3522#discussion_r574703724
+ testWidgets('uri can be null', (WidgetTester tester) async {
+ await tester.pumpWidget(Directionality(
+ textDirection: TextDirection.ltr,
+ child: WebLinkDelegate(TestLinkInfo(
+ uri: null,
+ target: LinkTarget.defaultTarget,
+ builder: (BuildContext context, FollowLink? followLink) {
+ return Container(width: 100, height: 100);
+ },
+ )),
+ ));
+ // Platform view creation happens asynchronously.
+ await tester.pumpAndSettle();
+
+ final html.Element anchor = _findSingleAnchor();
+ expect(anchor.hasAttribute('href'), false);
+ });
+ });
+}
+
+html.Element _findSingleAnchor() {
+ final List<html.Element> foundAnchors = <html.Element>[];
+ for (final html.Element anchor in html.document.querySelectorAll('a')) {
+ if (hasProperty(anchor, linkViewIdProperty)) {
+ foundAnchors.add(anchor);
+ }
+ }
+
+ // Search inside platform views with shadow roots as well.
+ for (final html.Element platformView
+ in html.document.querySelectorAll('flt-platform-view')) {
+ final html.ShadowRoot shadowRoot = platformView.shadowRoot!;
+ if (shadowRoot != null) {
+ for (final html.Element anchor in shadowRoot.querySelectorAll('a')) {
+ if (hasProperty(anchor, linkViewIdProperty)) {
+ foundAnchors.add(anchor);
+ }
+ }
+ }
+ }
+
+ return foundAnchors.single;
+}
+
+class TestLinkInfo extends LinkInfo {
+ @override
+ final LinkWidgetBuilder builder;
+
+ @override
+ final Uri? uri;
+
+ @override
+ final LinkTarget target;
+
+ @override
+ bool get isDisabled => uri == null;
+
+ TestLinkInfo({
+ required this.uri,
+ required this.target,
+ required this.builder,
+ });
+}
diff --git a/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.dart b/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.dart
new file mode 100644
index 0000000..f7ea356
--- /dev/null
+++ b/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.dart
@@ -0,0 +1,202 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:html' as html;
+import 'package:flutter_test/flutter_test.dart';
+import 'package:mockito/annotations.dart';
+import 'package:url_launcher_web/url_launcher_web.dart';
+import 'package:mockito/mockito.dart';
+import 'package:integration_test/integration_test.dart';
+
+import 'url_launcher_web_test.mocks.dart';
+
+@GenerateMocks([html.Window, html.Navigator])
+void main() {
+ IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+
+ group('UrlLauncherPlugin', () {
+ late MockWindow mockWindow;
+ late MockNavigator mockNavigator;
+
+ late UrlLauncherPlugin plugin;
+
+ setUp(() {
+ mockWindow = MockWindow();
+ mockNavigator = MockNavigator();
+ when(mockWindow.navigator).thenReturn(mockNavigator);
+
+ // Simulate that window.open does something.
+ when(mockWindow.open(any, any)).thenReturn(MockWindow());
+
+ when(mockNavigator.vendor).thenReturn('Google LLC');
+ when(mockNavigator.appVersion).thenReturn('Mock version!');
+
+ plugin = UrlLauncherPlugin(debugWindow: mockWindow);
+ });
+
+ group('canLaunch', () {
+ testWidgets('"http" URLs -> true', (WidgetTester _) async {
+ expect(plugin.canLaunch('http://google.com'), completion(isTrue));
+ });
+
+ testWidgets('"https" URLs -> true', (WidgetTester _) async {
+ expect(
+ plugin.canLaunch('https://go, (Widogle.com'), completion(isTrue));
+ });
+
+ testWidgets('"mailto" URLs -> true', (WidgetTester _) async {
+ expect(
+ plugin.canLaunch('mailto:name@mydomain.com'), completion(isTrue));
+ });
+
+ testWidgets('"tel" URLs -> true', (WidgetTester _) async {
+ expect(plugin.canLaunch('tel:5551234567'), completion(isTrue));
+ });
+
+ testWidgets('"sms" URLs -> true', (WidgetTester _) async {
+ expect(plugin.canLaunch('sms:+19725551212?body=hello%20there'),
+ completion(isTrue));
+ });
+ });
+
+ group('launch', () {
+ testWidgets('launching a URL returns true', (WidgetTester _) async {
+ expect(
+ plugin.launch(
+ 'https://www.google.com',
+ ),
+ completion(isTrue));
+ });
+
+ testWidgets('launching a "mailto" returns true', (WidgetTester _) async {
+ expect(
+ plugin.launch(
+ 'mailto:name@mydomain.com',
+ ),
+ completion(isTrue));
+ });
+
+ testWidgets('launching a "tel" returns true', (WidgetTester _) async {
+ expect(
+ plugin.launch(
+ 'tel:5551234567',
+ ),
+ completion(isTrue));
+ });
+
+ testWidgets('launching a "sms" returns true', (WidgetTester _) async {
+ expect(
+ plugin.launch(
+ 'sms:+19725551212?body=hello%20there',
+ ),
+ completion(isTrue));
+ });
+ });
+
+ group('openNewWindow', () {
+ testWidgets('http urls should be launched in a new window',
+ (WidgetTester _) async {
+ plugin.openNewWindow('http://www.google.com');
+
+ verify(mockWindow.open('http://www.google.com', ''));
+ });
+
+ testWidgets('https urls should be launched in a new window',
+ (WidgetTester _) async {
+ plugin.openNewWindow('https://www.google.com');
+
+ verify(mockWindow.open('https://www.google.com', ''));
+ });
+
+ testWidgets('mailto urls should be launched on a new window',
+ (WidgetTester _) async {
+ plugin.openNewWindow('mailto:name@mydomain.com');
+
+ verify(mockWindow.open('mailto:name@mydomain.com', ''));
+ });
+
+ testWidgets('tel urls should be launched on a new window',
+ (WidgetTester _) async {
+ plugin.openNewWindow('tel:5551234567');
+
+ verify(mockWindow.open('tel:5551234567', ''));
+ });
+
+ testWidgets('sms urls should be launched on a new window',
+ (WidgetTester _) async {
+ plugin.openNewWindow('sms:+19725551212?body=hello%20there');
+
+ verify(mockWindow.open('sms:+19725551212?body=hello%20there', ''));
+ });
+ testWidgets(
+ 'setting webOnlyLinkTarget as _self opens the url in the same tab',
+ (WidgetTester _) async {
+ plugin.openNewWindow('https://www.google.com',
+ webOnlyWindowName: '_self');
+ verify(mockWindow.open('https://www.google.com', '_self'));
+ });
+
+ testWidgets(
+ 'setting webOnlyLinkTarget as _blank opens the url in a new tab',
+ (WidgetTester _) async {
+ plugin.openNewWindow('https://www.google.com',
+ webOnlyWindowName: '_blank');
+ verify(mockWindow.open('https://www.google.com', '_blank'));
+ });
+
+ group('Safari', () {
+ setUp(() {
+ when(mockNavigator.vendor).thenReturn('Apple Computer, Inc.');
+ when(mockNavigator.appVersion).thenReturn(
+ '5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15');
+ // Recreate the plugin, so it grabs the overrides from this group
+ plugin = UrlLauncherPlugin(debugWindow: mockWindow);
+ });
+
+ testWidgets('http urls should be launched in a new window',
+ (WidgetTester _) async {
+ plugin.openNewWindow('http://www.google.com');
+
+ verify(mockWindow.open('http://www.google.com', ''));
+ });
+
+ testWidgets('https urls should be launched in a new window',
+ (WidgetTester _) async {
+ plugin.openNewWindow('https://www.google.com');
+
+ verify(mockWindow.open('https://www.google.com', ''));
+ });
+
+ testWidgets('mailto urls should be launched on the same window',
+ (WidgetTester _) async {
+ plugin.openNewWindow('mailto:name@mydomain.com');
+
+ verify(mockWindow.open('mailto:name@mydomain.com', '_top'));
+ });
+
+ testWidgets('tel urls should be launched on the same window',
+ (WidgetTester _) async {
+ plugin.openNewWindow('tel:5551234567');
+
+ verify(mockWindow.open('tel:5551234567', '_top'));
+ });
+
+ testWidgets('sms urls should be launched on the same window',
+ (WidgetTester _) async {
+ plugin.openNewWindow('sms:+19725551212?body=hello%20there');
+
+ verify(
+ mockWindow.open('sms:+19725551212?body=hello%20there', '_top'));
+ });
+ testWidgets(
+ 'mailto urls should use _blank if webOnlyWindowName is set as _blank',
+ (WidgetTester _) async {
+ plugin.openNewWindow('mailto:name@mydomain.com',
+ webOnlyWindowName: '_blank');
+ verify(mockWindow.open('mailto:name@mydomain.com', '_blank'));
+ });
+ });
+ });
+ });
+}
diff --git a/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.mocks.dart b/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.mocks.dart
new file mode 100644
index 0000000..73d3bf3
--- /dev/null
+++ b/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.mocks.dart
@@ -0,0 +1,660 @@
+import 'dart:async' as _i4;
+import 'dart:html' as _i2;
+import 'dart:math' as _i5;
+import 'dart:web_sql' as _i3;
+
+import 'package:mockito/mockito.dart' as _i1;
+
+// ignore_for_file: comment_references
+
+// ignore_for_file: unnecessary_parenthesis
+
+class _FakeDocument extends _i1.Fake implements _i2.Document {}
+
+class _FakeLocation extends _i1.Fake implements _i2.Location {}
+
+class _FakeConsole extends _i1.Fake implements _i2.Console {}
+
+class _FakeHistory extends _i1.Fake implements _i2.History {}
+
+class _FakeStorage extends _i1.Fake implements _i2.Storage {}
+
+class _FakeNavigator extends _i1.Fake implements _i2.Navigator {}
+
+class _FakePerformance extends _i1.Fake implements _i2.Performance {}
+
+class _FakeEvents extends _i1.Fake implements _i2.Events {}
+
+class _FakeType extends _i1.Fake implements Type {}
+
+class _FakeWindowBase extends _i1.Fake implements _i2.WindowBase {}
+
+class _FakeFileSystem extends _i1.Fake implements _i2.FileSystem {}
+
+class _FakeStylePropertyMapReadonly extends _i1.Fake
+ implements _i2.StylePropertyMapReadonly {}
+
+class _FakeMediaQueryList extends _i1.Fake implements _i2.MediaQueryList {}
+
+class _FakeEntry extends _i1.Fake implements _i2.Entry {}
+
+class _FakeSqlDatabase extends _i1.Fake implements _i3.SqlDatabase {}
+
+class _FakeGeolocation extends _i1.Fake implements _i2.Geolocation {}
+
+class _FakeMediaStream extends _i1.Fake implements _i2.MediaStream {}
+
+class _FakeRelatedApplication extends _i1.Fake
+ implements _i2.RelatedApplication {}
+
+/// A class which mocks [Window].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockWindow extends _i1.Mock implements _i2.Window {
+ MockWindow() {
+ _i1.throwOnMissingStub(this);
+ }
+
+ @override
+ _i4.Future<num> get animationFrame =>
+ (super.noSuchMethod(Invocation.getter(#animationFrame), Future.value(0))
+ as _i4.Future<num>);
+ @override
+ _i2.Document get document =>
+ (super.noSuchMethod(Invocation.getter(#document), _FakeDocument())
+ as _i2.Document);
+ @override
+ _i2.Location get location =>
+ (super.noSuchMethod(Invocation.getter(#location), _FakeLocation())
+ as _i2.Location);
+ @override
+ set location(_i2.LocationBase? value) =>
+ super.noSuchMethod(Invocation.setter(#location, value));
+ @override
+ _i2.Console get console =>
+ (super.noSuchMethod(Invocation.getter(#console), _FakeConsole())
+ as _i2.Console);
+ @override
+ num get devicePixelRatio =>
+ (super.noSuchMethod(Invocation.getter(#devicePixelRatio), 0) as num);
+ @override
+ _i2.History get history =>
+ (super.noSuchMethod(Invocation.getter(#history), _FakeHistory())
+ as _i2.History);
+ @override
+ _i2.Storage get localStorage =>
+ (super.noSuchMethod(Invocation.getter(#localStorage), _FakeStorage())
+ as _i2.Storage);
+ @override
+ _i2.Navigator get navigator =>
+ (super.noSuchMethod(Invocation.getter(#navigator), _FakeNavigator())
+ as _i2.Navigator);
+ @override
+ int get outerHeight =>
+ (super.noSuchMethod(Invocation.getter(#outerHeight), 0) as int);
+ @override
+ int get outerWidth =>
+ (super.noSuchMethod(Invocation.getter(#outerWidth), 0) as int);
+ @override
+ _i2.Performance get performance =>
+ (super.noSuchMethod(Invocation.getter(#performance), _FakePerformance())
+ as _i2.Performance);
+ @override
+ _i2.Storage get sessionStorage =>
+ (super.noSuchMethod(Invocation.getter(#sessionStorage), _FakeStorage())
+ as _i2.Storage);
+ @override
+ _i4.Stream<_i2.Event> get onContentLoaded => (super.noSuchMethod(
+ Invocation.getter(#onContentLoaded), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onAbort => (super
+ .noSuchMethod(Invocation.getter(#onAbort), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onBlur =>
+ (super.noSuchMethod(Invocation.getter(#onBlur), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onCanPlay => (super.noSuchMethod(
+ Invocation.getter(#onCanPlay), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onCanPlayThrough => (super.noSuchMethod(
+ Invocation.getter(#onCanPlayThrough), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onChange => (super
+ .noSuchMethod(Invocation.getter(#onChange), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.MouseEvent> get onClick => (super.noSuchMethod(
+ Invocation.getter(#onClick), Stream<_i2.MouseEvent>.empty())
+ as _i4.Stream<_i2.MouseEvent>);
+ @override
+ _i4.Stream<_i2.MouseEvent> get onContextMenu => (super.noSuchMethod(
+ Invocation.getter(#onContextMenu), Stream<_i2.MouseEvent>.empty())
+ as _i4.Stream<_i2.MouseEvent>);
+ @override
+ _i4.Stream<_i2.Event> get onDoubleClick => (super.noSuchMethod(
+ Invocation.getter(#onDoubleClick), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.DeviceMotionEvent> get onDeviceMotion => (super.noSuchMethod(
+ Invocation.getter(#onDeviceMotion),
+ Stream<_i2.DeviceMotionEvent>.empty())
+ as _i4.Stream<_i2.DeviceMotionEvent>);
+ @override
+ _i4.Stream<_i2.DeviceOrientationEvent> get onDeviceOrientation =>
+ (super.noSuchMethod(Invocation.getter(#onDeviceOrientation),
+ Stream<_i2.DeviceOrientationEvent>.empty())
+ as _i4.Stream<_i2.DeviceOrientationEvent>);
+ @override
+ _i4.Stream<_i2.MouseEvent> get onDrag => (super.noSuchMethod(
+ Invocation.getter(#onDrag), Stream<_i2.MouseEvent>.empty())
+ as _i4.Stream<_i2.MouseEvent>);
+ @override
+ _i4.Stream<_i2.MouseEvent> get onDragEnd => (super.noSuchMethod(
+ Invocation.getter(#onDragEnd), Stream<_i2.MouseEvent>.empty())
+ as _i4.Stream<_i2.MouseEvent>);
+ @override
+ _i4.Stream<_i2.MouseEvent> get onDragEnter => (super.noSuchMethod(
+ Invocation.getter(#onDragEnter), Stream<_i2.MouseEvent>.empty())
+ as _i4.Stream<_i2.MouseEvent>);
+ @override
+ _i4.Stream<_i2.MouseEvent> get onDragLeave => (super.noSuchMethod(
+ Invocation.getter(#onDragLeave), Stream<_i2.MouseEvent>.empty())
+ as _i4.Stream<_i2.MouseEvent>);
+ @override
+ _i4.Stream<_i2.MouseEvent> get onDragOver => (super.noSuchMethod(
+ Invocation.getter(#onDragOver), Stream<_i2.MouseEvent>.empty())
+ as _i4.Stream<_i2.MouseEvent>);
+ @override
+ _i4.Stream<_i2.MouseEvent> get onDragStart => (super.noSuchMethod(
+ Invocation.getter(#onDragStart), Stream<_i2.MouseEvent>.empty())
+ as _i4.Stream<_i2.MouseEvent>);
+ @override
+ _i4.Stream<_i2.MouseEvent> get onDrop => (super.noSuchMethod(
+ Invocation.getter(#onDrop), Stream<_i2.MouseEvent>.empty())
+ as _i4.Stream<_i2.MouseEvent>);
+ @override
+ _i4.Stream<_i2.Event> get onDurationChange => (super.noSuchMethod(
+ Invocation.getter(#onDurationChange), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onEmptied => (super.noSuchMethod(
+ Invocation.getter(#onEmptied), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onEnded => (super
+ .noSuchMethod(Invocation.getter(#onEnded), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onError => (super
+ .noSuchMethod(Invocation.getter(#onError), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onFocus => (super
+ .noSuchMethod(Invocation.getter(#onFocus), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onHashChange => (super.noSuchMethod(
+ Invocation.getter(#onHashChange), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onInput => (super
+ .noSuchMethod(Invocation.getter(#onInput), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onInvalid => (super.noSuchMethod(
+ Invocation.getter(#onInvalid), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.KeyboardEvent> get onKeyDown => (super.noSuchMethod(
+ Invocation.getter(#onKeyDown), Stream<_i2.KeyboardEvent>.empty())
+ as _i4.Stream<_i2.KeyboardEvent>);
+ @override
+ _i4.Stream<_i2.KeyboardEvent> get onKeyPress => (super.noSuchMethod(
+ Invocation.getter(#onKeyPress), Stream<_i2.KeyboardEvent>.empty())
+ as _i4.Stream<_i2.KeyboardEvent>);
+ @override
+ _i4.Stream<_i2.KeyboardEvent> get onKeyUp => (super.noSuchMethod(
+ Invocation.getter(#onKeyUp), Stream<_i2.KeyboardEvent>.empty())
+ as _i4.Stream<_i2.KeyboardEvent>);
+ @override
+ _i4.Stream<_i2.Event> get onLoad =>
+ (super.noSuchMethod(Invocation.getter(#onLoad), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onLoadedData => (super.noSuchMethod(
+ Invocation.getter(#onLoadedData), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onLoadedMetadata => (super.noSuchMethod(
+ Invocation.getter(#onLoadedMetadata), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onLoadStart => (super.noSuchMethod(
+ Invocation.getter(#onLoadStart), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.MessageEvent> get onMessage => (super.noSuchMethod(
+ Invocation.getter(#onMessage), Stream<_i2.MessageEvent>.empty())
+ as _i4.Stream<_i2.MessageEvent>);
+ @override
+ _i4.Stream<_i2.MouseEvent> get onMouseDown => (super.noSuchMethod(
+ Invocation.getter(#onMouseDown), Stream<_i2.MouseEvent>.empty())
+ as _i4.Stream<_i2.MouseEvent>);
+ @override
+ _i4.Stream<_i2.MouseEvent> get onMouseEnter => (super.noSuchMethod(
+ Invocation.getter(#onMouseEnter), Stream<_i2.MouseEvent>.empty())
+ as _i4.Stream<_i2.MouseEvent>);
+ @override
+ _i4.Stream<_i2.MouseEvent> get onMouseLeave => (super.noSuchMethod(
+ Invocation.getter(#onMouseLeave), Stream<_i2.MouseEvent>.empty())
+ as _i4.Stream<_i2.MouseEvent>);
+ @override
+ _i4.Stream<_i2.MouseEvent> get onMouseMove => (super.noSuchMethod(
+ Invocation.getter(#onMouseMove), Stream<_i2.MouseEvent>.empty())
+ as _i4.Stream<_i2.MouseEvent>);
+ @override
+ _i4.Stream<_i2.MouseEvent> get onMouseOut => (super.noSuchMethod(
+ Invocation.getter(#onMouseOut), Stream<_i2.MouseEvent>.empty())
+ as _i4.Stream<_i2.MouseEvent>);
+ @override
+ _i4.Stream<_i2.MouseEvent> get onMouseOver => (super.noSuchMethod(
+ Invocation.getter(#onMouseOver), Stream<_i2.MouseEvent>.empty())
+ as _i4.Stream<_i2.MouseEvent>);
+ @override
+ _i4.Stream<_i2.MouseEvent> get onMouseUp => (super.noSuchMethod(
+ Invocation.getter(#onMouseUp), Stream<_i2.MouseEvent>.empty())
+ as _i4.Stream<_i2.MouseEvent>);
+ @override
+ _i4.Stream<_i2.WheelEvent> get onMouseWheel => (super.noSuchMethod(
+ Invocation.getter(#onMouseWheel), Stream<_i2.WheelEvent>.empty())
+ as _i4.Stream<_i2.WheelEvent>);
+ @override
+ _i4.Stream<_i2.Event> get onOffline => (super.noSuchMethod(
+ Invocation.getter(#onOffline), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onOnline => (super
+ .noSuchMethod(Invocation.getter(#onOnline), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onPageHide => (super.noSuchMethod(
+ Invocation.getter(#onPageHide), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onPageShow => (super.noSuchMethod(
+ Invocation.getter(#onPageShow), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onPause => (super
+ .noSuchMethod(Invocation.getter(#onPause), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onPlay =>
+ (super.noSuchMethod(Invocation.getter(#onPlay), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onPlaying => (super.noSuchMethod(
+ Invocation.getter(#onPlaying), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.PopStateEvent> get onPopState => (super.noSuchMethod(
+ Invocation.getter(#onPopState), Stream<_i2.PopStateEvent>.empty())
+ as _i4.Stream<_i2.PopStateEvent>);
+ @override
+ _i4.Stream<_i2.Event> get onProgress => (super.noSuchMethod(
+ Invocation.getter(#onProgress), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onRateChange => (super.noSuchMethod(
+ Invocation.getter(#onRateChange), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onReset => (super
+ .noSuchMethod(Invocation.getter(#onReset), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onResize => (super
+ .noSuchMethod(Invocation.getter(#onResize), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onScroll => (super
+ .noSuchMethod(Invocation.getter(#onScroll), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onSearch => (super
+ .noSuchMethod(Invocation.getter(#onSearch), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onSeeked => (super
+ .noSuchMethod(Invocation.getter(#onSeeked), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onSeeking => (super.noSuchMethod(
+ Invocation.getter(#onSeeking), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onSelect => (super
+ .noSuchMethod(Invocation.getter(#onSelect), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onStalled => (super.noSuchMethod(
+ Invocation.getter(#onStalled), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.StorageEvent> get onStorage => (super.noSuchMethod(
+ Invocation.getter(#onStorage), Stream<_i2.StorageEvent>.empty())
+ as _i4.Stream<_i2.StorageEvent>);
+ @override
+ _i4.Stream<_i2.Event> get onSubmit => (super
+ .noSuchMethod(Invocation.getter(#onSubmit), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onSuspend => (super.noSuchMethod(
+ Invocation.getter(#onSuspend), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onTimeUpdate => (super.noSuchMethod(
+ Invocation.getter(#onTimeUpdate), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.TouchEvent> get onTouchCancel => (super.noSuchMethod(
+ Invocation.getter(#onTouchCancel), Stream<_i2.TouchEvent>.empty())
+ as _i4.Stream<_i2.TouchEvent>);
+ @override
+ _i4.Stream<_i2.TouchEvent> get onTouchEnd => (super.noSuchMethod(
+ Invocation.getter(#onTouchEnd), Stream<_i2.TouchEvent>.empty())
+ as _i4.Stream<_i2.TouchEvent>);
+ @override
+ _i4.Stream<_i2.TouchEvent> get onTouchMove => (super.noSuchMethod(
+ Invocation.getter(#onTouchMove), Stream<_i2.TouchEvent>.empty())
+ as _i4.Stream<_i2.TouchEvent>);
+ @override
+ _i4.Stream<_i2.TouchEvent> get onTouchStart => (super.noSuchMethod(
+ Invocation.getter(#onTouchStart), Stream<_i2.TouchEvent>.empty())
+ as _i4.Stream<_i2.TouchEvent>);
+ @override
+ _i4.Stream<_i2.TransitionEvent> get onTransitionEnd => (super.noSuchMethod(
+ Invocation.getter(#onTransitionEnd),
+ Stream<_i2.TransitionEvent>.empty()) as _i4.Stream<_i2.TransitionEvent>);
+ @override
+ _i4.Stream<_i2.Event> get onUnload => (super
+ .noSuchMethod(Invocation.getter(#onUnload), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onVolumeChange => (super.noSuchMethod(
+ Invocation.getter(#onVolumeChange), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.Event> get onWaiting => (super.noSuchMethod(
+ Invocation.getter(#onWaiting), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.AnimationEvent> get onAnimationEnd => (super.noSuchMethod(
+ Invocation.getter(#onAnimationEnd),
+ Stream<_i2.AnimationEvent>.empty()) as _i4.Stream<_i2.AnimationEvent>);
+ @override
+ _i4.Stream<_i2.AnimationEvent> get onAnimationIteration =>
+ (super.noSuchMethod(Invocation.getter(#onAnimationIteration),
+ Stream<_i2.AnimationEvent>.empty())
+ as _i4.Stream<_i2.AnimationEvent>);
+ @override
+ _i4.Stream<_i2.AnimationEvent> get onAnimationStart => (super.noSuchMethod(
+ Invocation.getter(#onAnimationStart),
+ Stream<_i2.AnimationEvent>.empty()) as _i4.Stream<_i2.AnimationEvent>);
+ @override
+ _i4.Stream<_i2.Event> get onBeforeUnload => (super.noSuchMethod(
+ Invocation.getter(#onBeforeUnload), Stream<_i2.Event>.empty())
+ as _i4.Stream<_i2.Event>);
+ @override
+ _i4.Stream<_i2.WheelEvent> get onWheel => (super.noSuchMethod(
+ Invocation.getter(#onWheel), Stream<_i2.WheelEvent>.empty())
+ as _i4.Stream<_i2.WheelEvent>);
+ @override
+ int get pageXOffset =>
+ (super.noSuchMethod(Invocation.getter(#pageXOffset), 0) as int);
+ @override
+ int get pageYOffset =>
+ (super.noSuchMethod(Invocation.getter(#pageYOffset), 0) as int);
+ @override
+ int get scrollX =>
+ (super.noSuchMethod(Invocation.getter(#scrollX), 0) as int);
+ @override
+ int get scrollY =>
+ (super.noSuchMethod(Invocation.getter(#scrollY), 0) as int);
+ @override
+ _i2.Events get on =>
+ (super.noSuchMethod(Invocation.getter(#on), _FakeEvents()) as _i2.Events);
+ @override
+ int get hashCode =>
+ (super.noSuchMethod(Invocation.getter(#hashCode), 0) as int);
+ @override
+ Type get runtimeType =>
+ (super.noSuchMethod(Invocation.getter(#runtimeType), _FakeType())
+ as Type);
+ @override
+ _i2.WindowBase open(String? url, String? name, [String? options]) =>
+ (super.noSuchMethod(
+ Invocation.method(#open, [url, name, options]), _FakeWindowBase())
+ as _i2.WindowBase);
+ @override
+ int requestAnimationFrame(_i2.FrameRequestCallback? callback) =>
+ (super.noSuchMethod(
+ Invocation.method(#requestAnimationFrame, [callback]), 0) as int);
+ @override
+ void cancelAnimationFrame(int? id) =>
+ super.noSuchMethod(Invocation.method(#cancelAnimationFrame, [id]));
+ @override
+ _i4.Future<_i2.FileSystem> requestFileSystem(int? size, {bool? persistent}) =>
+ (super.noSuchMethod(
+ Invocation.method(
+ #requestFileSystem, [size], {#persistent: persistent}),
+ Future.value(_FakeFileSystem())) as _i4.Future<_i2.FileSystem>);
+ @override
+ void cancelIdleCallback(int? handle) =>
+ super.noSuchMethod(Invocation.method(#cancelIdleCallback, [handle]));
+ @override
+ bool confirm([String? message]) =>
+ (super.noSuchMethod(Invocation.method(#confirm, [message]), false)
+ as bool);
+ @override
+ _i4.Future<dynamic> fetch(dynamic input, [Map<dynamic, dynamic>? init]) =>
+ (super.noSuchMethod(
+ Invocation.method(#fetch, [input, init]), Future.value(null))
+ as _i4.Future<dynamic>);
+ @override
+ bool find(String? string, bool? caseSensitive, bool? backwards, bool? wrap,
+ bool? wholeWord, bool? searchInFrames, bool? showDialog) =>
+ (super.noSuchMethod(
+ Invocation.method(#find, [
+ string,
+ caseSensitive,
+ backwards,
+ wrap,
+ wholeWord,
+ searchInFrames,
+ showDialog
+ ]),
+ false) as bool);
+ @override
+ _i2.StylePropertyMapReadonly getComputedStyleMap(
+ _i2.Element? element, String? pseudoElement) =>
+ (super.noSuchMethod(
+ Invocation.method(#getComputedStyleMap, [element, pseudoElement]),
+ _FakeStylePropertyMapReadonly()) as _i2.StylePropertyMapReadonly);
+ @override
+ List<_i2.CssRule> getMatchedCssRules(
+ _i2.Element? element, String? pseudoElement) =>
+ (super.noSuchMethod(
+ Invocation.method(#getMatchedCssRules, [element, pseudoElement]),
+ <_i2.CssRule>[]) as List<_i2.CssRule>);
+ @override
+ _i2.MediaQueryList matchMedia(String? query) => (super.noSuchMethod(
+ Invocation.method(#matchMedia, [query]), _FakeMediaQueryList())
+ as _i2.MediaQueryList);
+ @override
+ void moveBy(int? x, int? y) =>
+ super.noSuchMethod(Invocation.method(#moveBy, [x, y]));
+ @override
+ void postMessage(dynamic message, String? targetOrigin,
+ [List<Object>? transfer]) =>
+ super.noSuchMethod(
+ Invocation.method(#postMessage, [message, targetOrigin, transfer]));
+ @override
+ int requestIdleCallback(_i2.IdleRequestCallback? callback,
+ [Map<dynamic, dynamic>? options]) =>
+ (super.noSuchMethod(
+ Invocation.method(#requestIdleCallback, [callback, options]), 0)
+ as int);
+ @override
+ void resizeBy(int? x, int? y) =>
+ super.noSuchMethod(Invocation.method(#resizeBy, [x, y]));
+ @override
+ void resizeTo(int? x, int? y) =>
+ super.noSuchMethod(Invocation.method(#resizeTo, [x, y]));
+ @override
+ _i4.Future<_i2.Entry> resolveLocalFileSystemUrl(String? url) =>
+ (super.noSuchMethod(Invocation.method(#resolveLocalFileSystemUrl, [url]),
+ Future.value(_FakeEntry())) as _i4.Future<_i2.Entry>);
+ @override
+ String atob(String? atob) =>
+ (super.noSuchMethod(Invocation.method(#atob, [atob]), '') as String);
+ @override
+ String btoa(String? btoa) =>
+ (super.noSuchMethod(Invocation.method(#btoa, [btoa]), '') as String);
+ @override
+ void moveTo(_i5.Point<num>? p) =>
+ super.noSuchMethod(Invocation.method(#moveTo, [p]));
+ @override
+ _i3.SqlDatabase openDatabase(String? name, String? version,
+ String? displayName, int? estimatedSize,
+ [_i2.DatabaseCallback? creationCallback]) =>
+ (super.noSuchMethod(
+ Invocation.method(#openDatabase,
+ [name, version, displayName, estimatedSize, creationCallback]),
+ _FakeSqlDatabase()) as _i3.SqlDatabase);
+ @override
+ void addEventListener(String? type, _i2.EventListener? listener,
+ [bool? useCapture]) =>
+ super.noSuchMethod(
+ Invocation.method(#addEventListener, [type, listener, useCapture]));
+ @override
+ void removeEventListener(String? type, _i2.EventListener? listener,
+ [bool? useCapture]) =>
+ super.noSuchMethod(Invocation.method(
+ #removeEventListener, [type, listener, useCapture]));
+ @override
+ bool dispatchEvent(_i2.Event? event) =>
+ (super.noSuchMethod(Invocation.method(#dispatchEvent, [event]), false)
+ as bool);
+ @override
+ bool operator ==(Object? other) =>
+ (super.noSuchMethod(Invocation.method(#==, [other]), false) as bool);
+ @override
+ String toString() =>
+ (super.noSuchMethod(Invocation.method(#toString, []), '') as String);
+}
+
+/// A class which mocks [Navigator].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockNavigator extends _i1.Mock implements _i2.Navigator {
+ MockNavigator() {
+ _i1.throwOnMissingStub(this);
+ }
+
+ @override
+ String get language =>
+ (super.noSuchMethod(Invocation.getter(#language), '') as String);
+ @override
+ _i2.Geolocation get geolocation =>
+ (super.noSuchMethod(Invocation.getter(#geolocation), _FakeGeolocation())
+ as _i2.Geolocation);
+ @override
+ String get vendor =>
+ (super.noSuchMethod(Invocation.getter(#vendor), '') as String);
+ @override
+ String get vendorSub =>
+ (super.noSuchMethod(Invocation.getter(#vendorSub), '') as String);
+ @override
+ String get appCodeName =>
+ (super.noSuchMethod(Invocation.getter(#appCodeName), '') as String);
+ @override
+ String get appName =>
+ (super.noSuchMethod(Invocation.getter(#appName), '') as String);
+ @override
+ String get appVersion =>
+ (super.noSuchMethod(Invocation.getter(#appVersion), '') as String);
+ @override
+ String get product =>
+ (super.noSuchMethod(Invocation.getter(#product), '') as String);
+ @override
+ String get userAgent =>
+ (super.noSuchMethod(Invocation.getter(#userAgent), '') as String);
+ @override
+ int get hashCode =>
+ (super.noSuchMethod(Invocation.getter(#hashCode), 0) as int);
+ @override
+ Type get runtimeType =>
+ (super.noSuchMethod(Invocation.getter(#runtimeType), _FakeType())
+ as Type);
+ @override
+ List<_i2.Gamepad?> getGamepads() =>
+ (super.noSuchMethod(Invocation.method(#getGamepads, []), <_i2.Gamepad?>[])
+ as List<_i2.Gamepad?>);
+ @override
+ _i4.Future<_i2.MediaStream> getUserMedia({dynamic audio, dynamic video}) =>
+ (super.noSuchMethod(
+ Invocation.method(#getUserMedia, [], {#audio: audio, #video: video}),
+ Future.value(_FakeMediaStream())) as _i4.Future<_i2.MediaStream>);
+ @override
+ _i4.Future<dynamic> getBattery() => (super
+ .noSuchMethod(Invocation.method(#getBattery, []), Future.value(null))
+ as _i4.Future<dynamic>);
+ @override
+ _i4.Future<_i2.RelatedApplication> getInstalledRelatedApps() =>
+ (super.noSuchMethod(Invocation.method(#getInstalledRelatedApps, []),
+ Future.value(_FakeRelatedApplication()))
+ as _i4.Future<_i2.RelatedApplication>);
+ @override
+ _i4.Future<dynamic> getVRDisplays() => (super.noSuchMethod(
+ Invocation.method(#getVRDisplays, []), Future.value(null))
+ as _i4.Future<dynamic>);
+ @override
+ void registerProtocolHandler(String? scheme, String? url, String? title) =>
+ super.noSuchMethod(
+ Invocation.method(#registerProtocolHandler, [scheme, url, title]));
+ @override
+ _i4.Future<dynamic> requestKeyboardLock([List<String>? keyCodes]) =>
+ (super.noSuchMethod(Invocation.method(#requestKeyboardLock, [keyCodes]),
+ Future.value(null)) as _i4.Future<dynamic>);
+ @override
+ _i4.Future<dynamic> requestMidiAccess([Map<dynamic, dynamic>? options]) =>
+ (super.noSuchMethod(Invocation.method(#requestMidiAccess, [options]),
+ Future.value(null)) as _i4.Future<dynamic>);
+ @override
+ _i4.Future<dynamic> requestMediaKeySystemAccess(String? keySystem,
+ List<Map<dynamic, dynamic>>? supportedConfigurations) =>
+ (super.noSuchMethod(
+ Invocation.method(#requestMediaKeySystemAccess,
+ [keySystem, supportedConfigurations]),
+ Future.value(null)) as _i4.Future<dynamic>);
+ @override
+ bool sendBeacon(String? url, Object? data) =>
+ (super.noSuchMethod(Invocation.method(#sendBeacon, [url, data]), false)
+ as bool);
+ @override
+ _i4.Future<dynamic> share([Map<dynamic, dynamic>? data]) =>
+ (super.noSuchMethod(Invocation.method(#share, [data]), Future.value(null))
+ as _i4.Future<dynamic>);
+ @override
+ bool operator ==(Object? other) =>
+ (super.noSuchMethod(Invocation.method(#==, [other]), false) as bool);
+ @override
+ String toString() =>
+ (super.noSuchMethod(Invocation.method(#toString, []), '') as String);
+}
diff --git a/packages/url_launcher/url_launcher_web/test/lib/main.dart b/packages/url_launcher/url_launcher_web/example/lib/main.dart
similarity index 100%
rename from packages/url_launcher/url_launcher_web/test/lib/main.dart
rename to packages/url_launcher/url_launcher_web/example/lib/main.dart
diff --git a/packages/url_launcher/url_launcher_web/test/pubspec.yaml b/packages/url_launcher/url_launcher_web/example/pubspec.yaml
similarity index 61%
rename from packages/url_launcher/url_launcher_web/test/pubspec.yaml
rename to packages/url_launcher/url_launcher_web/example/pubspec.yaml
index b8c541f..5fc060f 100644
--- a/packages/url_launcher/url_launcher_web/test/pubspec.yaml
+++ b/packages/url_launcher/url_launcher_web/example/pubspec.yaml
@@ -1,22 +1,22 @@
name: regular_integration_tests
publish_to: none
-environment:
- sdk: ">=2.10.0-56.0.dev <3.0.0"
-
dependencies:
flutter:
sdk: flutter
dev_dependencies:
+ build_runner: ^1.10.0
+ mockito: ^5.0.0-nullsafety.5
+ url_launcher_web:
+ path: ../
flutter_driver:
sdk: flutter
flutter_test:
sdk: flutter
- http: ^0.12.2
- mockito: ^4.1.1
- url_launcher_web:
- path: ../
integration_test:
- path: ../../../integration_test
+ sdk: flutter
+environment:
+ sdk: ">=2.12.0-0 <3.0.0"
+ flutter: ">=1.26.0-0" # For integration_test from sdk
diff --git a/packages/url_launcher/url_launcher_web/example/run_test.sh b/packages/url_launcher/url_launcher_web/example/run_test.sh
new file mode 100755
index 0000000..b243f29
--- /dev/null
+++ b/packages/url_launcher/url_launcher_web/example/run_test.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/bash
+if pgrep -lf chromedriver > /dev/null; then
+ echo "chromedriver is running."
+
+ flutter pub get
+
+ echo "(Re)generating mocks."
+ flutter pub run build_runner build --delete-conflicting-outputs
+
+ if [ $# -eq 0 ]; then
+ echo "No target specified, running all tests..."
+ find integration_test/ -iname *_test.dart | xargs -n1 -i -t flutter drive -d web-server --web-port=7357 --browser-name=chrome --driver=test_driver/integration_test_driver.dart --target='{}'
+ else
+ echo "Running test target: $1..."
+ set -x
+ flutter drive -d web-server --web-port=7357 --browser-name=chrome --driver=test_driver/integration_test_driver.dart --target=$1
+ fi
+
+ else
+ echo "chromedriver is not running."
+ echo "Please, check the README.md for instructions on how to use run_test.sh"
+fi
+
diff --git a/packages/url_launcher/url_launcher_web/test/test_driver/url_launcher_web_integration_test.dart b/packages/url_launcher/url_launcher_web/example/test_driver/integration_test_driver.dart
similarity index 94%
rename from packages/url_launcher/url_launcher_web/test/test_driver/url_launcher_web_integration_test.dart
rename to packages/url_launcher/url_launcher_web/example/test_driver/integration_test_driver.dart
index 2d68bb9..64e2248 100644
--- a/packages/url_launcher/url_launcher_web/test/test_driver/url_launcher_web_integration_test.dart
+++ b/packages/url_launcher/url_launcher_web/example/test_driver/integration_test_driver.dart
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// @dart = 2.9
import 'package:integration_test/integration_test_driver.dart';
Future<void> main() async => integrationDriver();
diff --git a/packages/url_launcher/url_launcher_web/test/web/index.html b/packages/url_launcher/url_launcher_web/example/web/index.html
similarity index 100%
rename from packages/url_launcher/url_launcher_web/test/web/index.html
rename to packages/url_launcher/url_launcher_web/example/web/index.html
diff --git a/packages/url_launcher/url_launcher_web/lib/src/link.dart b/packages/url_launcher/url_launcher_web/lib/src/link.dart
index 8169a9c..42c711b 100644
--- a/packages/url_launcher/url_launcher_web/lib/src/link.dart
+++ b/packages/url_launcher/url_launcher_web/lib/src/link.dart
@@ -45,16 +45,16 @@
/// For external URIs, it lets the browser do its thing. For app route names, it
/// pushes the route name to the framework.
class WebLinkDelegateState extends State<WebLinkDelegate> {
- LinkViewController _controller;
+ late LinkViewController _controller;
@override
void didUpdateWidget(WebLinkDelegate oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.link.uri != oldWidget.link.uri) {
- _controller?.setUri(widget.link.uri);
+ _controller.setUri(widget.link.uri);
}
if (widget.link.target != oldWidget.link.target) {
- _controller?.setTarget(widget.link.target);
+ _controller.setTarget(widget.link.target);
}
}
@@ -126,15 +126,15 @@
static Map<int, LinkViewController> _instances = <int, LinkViewController>{};
static html.Element _viewFactory(int viewId) {
- return _instances[viewId]?._element;
+ return _instances[viewId]!._element;
}
- static int _hitTestedViewId;
+ static int? _hitTestedViewId;
- static StreamSubscription _clickSubscription;
+ static late StreamSubscription _clickSubscription;
static void _onGlobalClick(html.MouseEvent event) {
- final int viewId = getViewIdFromTarget(event);
+ final int? viewId = getViewIdFromTarget(event);
_instances[viewId]?._onDomClick(event);
// After the DOM click event has been received, clean up the hit test state
// so we can start fresh on the next click.
@@ -161,7 +161,7 @@
/// The context of the [Link] widget that created this controller.
final BuildContext context;
- html.Element _element;
+ late html.Element _element;
bool get _isInitialized => _element != null;
Future<void> _initialize() async {
@@ -193,7 +193,7 @@
return;
}
- if (_uri.hasScheme) {
+ if (_uri != null && _uri!.hasScheme) {
// External links will be handled by the browser, so we don't have to do
// anything.
return;
@@ -207,10 +207,12 @@
pushRouteNameToFramework(context, routeName);
}
- Uri _uri;
+ Uri? _uri;
/// Set the [Uri] value for this link.
- void setUri(Uri uri) {
+ ///
+ /// When Uri is null, the `href` attribute of the link is removed.
+ void setUri(Uri? uri) {
assert(_isInitialized);
_uri = uri;
if (uri == null) {
@@ -264,8 +266,8 @@
}
/// Finds the view id of the DOM element targeted by the [event].
-int getViewIdFromTarget(html.Event event) {
- final html.Element linkElement = getLinkElementFromTarget(event);
+int? getViewIdFromTarget(html.Event event) {
+ final html.Element? linkElement = getLinkElementFromTarget(event);
if (linkElement != null) {
return getProperty(linkElement, linkViewIdProperty);
}
@@ -275,15 +277,17 @@
/// Finds the targeted DOM element by the [event].
///
/// It handles the case where the target element is inside a shadow DOM too.
-html.Element getLinkElementFromTarget(html.Event event) {
- final html.Element target = event.target;
- if (isLinkElement(target)) {
- return target;
- }
- if (target.shadowRoot != null) {
- final html.Element child = target.shadowRoot.lastChild;
- if (isLinkElement(child)) {
- return child;
+html.Element? getLinkElementFromTarget(html.Event event) {
+ final html.EventTarget? target = event.target;
+ if (target != null && target is html.Element) {
+ if (isLinkElement(target)) {
+ return target;
+ }
+ if (target.shadowRoot != null) {
+ final html.Node? child = target.shadowRoot!.lastChild;
+ if (child != null && child is html.Element && isLinkElement(child)) {
+ return child;
+ }
}
}
return null;
@@ -291,6 +295,8 @@
/// Checks if the given [element] is a link that was created by
/// [LinkViewController].
-bool isLinkElement(html.Element element) {
- return element.tagName == 'A' && hasProperty(element, linkViewIdProperty);
+bool isLinkElement(html.Element? element) {
+ return element != null &&
+ element.tagName == 'A' &&
+ hasProperty(element, linkViewIdProperty);
}
diff --git a/packages/url_launcher/url_launcher_web/lib/url_launcher_web.dart b/packages/url_launcher/url_launcher_web/lib/url_launcher_web.dart
index 969cfba..e4d2116 100644
--- a/packages/url_launcher/url_launcher_web/lib/url_launcher_web.dart
+++ b/packages/url_launcher/url_launcher_web/lib/url_launcher_web.dart
@@ -19,7 +19,7 @@
'tel',
'sms',
};
-String _getUrlScheme(String url) => Uri.tryParse(url)?.scheme;
+String? _getUrlScheme(String url) => Uri.tryParse(url)?.scheme;
bool _isSafariTargetTopScheme(String url) =>
_safariTargetTopSchemes.contains(_getUrlScheme(url));
@@ -38,7 +38,7 @@
}.union(_safariTargetTopSchemes);
/// A constructor that allows tests to override the window object used by the plugin.
- UrlLauncherPlugin({@visibleForTesting html.Window debugWindow})
+ UrlLauncherPlugin({@visibleForTesting html.Window? debugWindow})
: _window = debugWindow ?? html.window {
_isSafari = navigatorIsSafari(_window.navigator);
}
@@ -58,7 +58,7 @@
///
/// Returns the newly created window.
@visibleForTesting
- html.WindowBase openNewWindow(String url, {String webOnlyWindowName}) {
+ html.WindowBase openNewWindow(String url, {String? webOnlyWindowName}) {
// We need to open mailto, tel and sms urls on the _top window context on safari browsers.
// See https://github.com/flutter/flutter/issues/51461 for reference.
final target = webOnlyWindowName ??
@@ -74,13 +74,13 @@
@override
Future<bool> launch(
String url, {
- @required bool useSafariVC,
- @required bool useWebView,
- @required bool enableJavaScript,
- @required bool enableDomStorage,
- @required bool universalLinksOnly,
- @required Map<String, String> headers,
- String webOnlyWindowName,
+ bool useSafariVC = false,
+ bool useWebView = false,
+ bool enableJavaScript = false,
+ bool enableDomStorage = false,
+ bool universalLinksOnly = false,
+ Map<String, String> headers = const <String, String>{},
+ String? webOnlyWindowName,
}) {
return Future<bool>.value(
openNewWindow(url, webOnlyWindowName: webOnlyWindowName) != null);
diff --git a/packages/url_launcher/url_launcher_web/pubspec.yaml b/packages/url_launcher/url_launcher_web/pubspec.yaml
index 77a9586..b9f957a 100644
--- a/packages/url_launcher/url_launcher_web/pubspec.yaml
+++ b/packages/url_launcher/url_launcher_web/pubspec.yaml
@@ -1,10 +1,7 @@
name: url_launcher_web
description: Web platform implementation of url_launcher
homepage: https://github.com/flutter/plugins/tree/master/packages/url_launcher/url_launcher_web
-# 0.1.y+z is compatible with 1.0.0, if you land a breaking change bump
-# the version to 2.0.0.
-# See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0
-version: 0.1.5+3
+version: 2.0.0-nullsafety
flutter:
plugin:
@@ -14,31 +11,18 @@
fileName: url_launcher_web.dart
dependencies:
- url_launcher_platform_interface: ^1.0.9
- # TODO(mvanbeusekom): Update to use pub.dev once null safety version is published.
- # url_launcher_platform_interface:
- # git:
- # url: https://github.com/flutter/plugins.git
- # ref: nnbd
- # path: packages/url_launcher/url_launcher_platform_interface
+ url_launcher_platform_interface: ^2.0.0-nullsafety
+ meta: ^1.3.0 # null safe
flutter:
sdk: flutter
flutter_web_plugins:
sdk: flutter
- meta: ^1.1.7
dev_dependencies:
+ pedantic: ^1.10.0 # null safe
flutter_test:
sdk: flutter
- url_launcher: ^5.2.5
- # TODO(mvanbeusekom): Update to use pub.dev once null safety version is published.
- # url_launcher:
- # path: ../url_launcher
- pedantic: ^1.8.0
- mockito: ^4.1.1
- integration_test:
- path: ../../integration_test
environment:
- sdk: ">=2.2.0 <3.0.0"
- flutter: ">=1.10.0"
+ sdk: ">=2.12.0-0 <3.0.0"
+ flutter: ">=1.12.13+hotfix.5"
diff --git a/packages/url_launcher/url_launcher_web/test/README.md b/packages/url_launcher/url_launcher_web/test/README.md
index 7c48d02..7c5b4ad 100644
--- a/packages/url_launcher/url_launcher_web/test/README.md
+++ b/packages/url_launcher/url_launcher_web/test/README.md
@@ -1,17 +1,5 @@
-# Running browser_tests
+## test
-Make sure you have updated to the latest Flutter master.
+This package uses integration tests for testing.
-1. Check what version of Chrome is running on the machine you're running tests on.
-
-2. Download and install driver for that version from here:
- * <https://chromedriver.chromium.org/downloads>
-
-3. Start the driver using `chromedriver --port=4444`
-
-4. Change into the `test` directory of your clone.
-
-5. Run tests: `flutter drive -d web-server --browser-name=chrome --target=test_driver/TEST_NAME_integration.dart`, or (in Linux):
-
- * Single: `./run_test test_driver/TEST_NAME_integration.dart`
- * All: `./run_test`
+See `example/README.md` for more info.
diff --git a/packages/url_launcher/url_launcher_web/test/run_test b/packages/url_launcher/url_launcher_web/test/run_test
deleted file mode 100755
index 74a8526..0000000
--- a/packages/url_launcher/url_launcher_web/test/run_test
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/bash
-if pgrep -lf chromedriver > /dev/null; then
- echo "chromedriver is running."
-
- if [ $# -eq 0 ]; then
- echo "No target specified, running all tests..."
- find test_driver/ -iname *_integration.dart | xargs -n1 -i -t flutter drive -d web-server --web-port=7357 --browser-name=chrome --target='{}'
- else
- echo "Running test target: $1..."
- set -x
- flutter drive -d web-server --web-port=7357 --browser-name=chrome --target=$1
- fi
-
- else
- echo "chromedriver is not running."
-fi
-
diff --git a/packages/url_launcher/url_launcher_web/test/test_driver/url_launcher_web_integration.dart b/packages/url_launcher/url_launcher_web/test/test_driver/url_launcher_web_integration.dart
deleted file mode 100644
index bfa9482..0000000
--- a/packages/url_launcher/url_launcher_web/test/test_driver/url_launcher_web_integration.dart
+++ /dev/null
@@ -1,352 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// @dart = 2.9
-import 'dart:html' as html;
-import 'dart:js_util';
-import 'package:flutter/widgets.dart';
-import 'package:flutter_test/flutter_test.dart';
-import 'package:url_launcher_platform_interface/link.dart';
-import 'package:url_launcher_web/url_launcher_web.dart';
-import 'package:url_launcher_web/src/link.dart';
-import 'package:mockito/mockito.dart';
-import 'package:integration_test/integration_test.dart';
-
-class _MockWindow extends Mock implements html.Window {}
-
-class _MockNavigator extends Mock implements html.Navigator {}
-
-void main() {
- IntegrationTestWidgetsFlutterBinding.ensureInitialized();
-
- group('UrlLauncherPlugin', () {
- _MockWindow mockWindow;
- _MockNavigator mockNavigator;
-
- UrlLauncherPlugin plugin;
-
- setUp(() {
- mockWindow = _MockWindow();
- mockNavigator = _MockNavigator();
- when(mockWindow.navigator).thenReturn(mockNavigator);
-
- plugin = UrlLauncherPlugin(debugWindow: mockWindow);
- });
-
- group('canLaunch', () {
- testWidgets('"http" URLs -> true', (WidgetTester _) async {
- expect(plugin.canLaunch('http://google.com'), completion(isTrue));
- });
-
- testWidgets('"https" URLs -> true', (WidgetTester _) async {
- expect(
- plugin.canLaunch('https://go, (Widogle.com'), completion(isTrue));
- });
-
- testWidgets('"mailto" URLs -> true', (WidgetTester _) async {
- expect(
- plugin.canLaunch('mailto:name@mydomain.com'), completion(isTrue));
- });
-
- testWidgets('"tel" URLs -> true', (WidgetTester _) async {
- expect(plugin.canLaunch('tel:5551234567'), completion(isTrue));
- });
-
- testWidgets('"sms" URLs -> true', (WidgetTester _) async {
- expect(plugin.canLaunch('sms:+19725551212?body=hello%20there'),
- completion(isTrue));
- });
- });
-
- group('launch', () {
- setUp(() {
- // Simulate that window.open does something.
- when(mockWindow.open('https://www.google.com', ''))
- .thenReturn(_MockWindow());
- when(mockWindow.open('mailto:name@mydomain.com', ''))
- .thenReturn(_MockWindow());
- when(mockWindow.open('tel:5551234567', '')).thenReturn(_MockWindow());
- when(mockWindow.open('sms:+19725551212?body=hello%20there', ''))
- .thenReturn(_MockWindow());
- });
-
- testWidgets('launching a URL returns true', (WidgetTester _) async {
- expect(
- plugin.launch(
- 'https://www.google.com',
- useSafariVC: null,
- useWebView: null,
- universalLinksOnly: null,
- enableDomStorage: null,
- enableJavaScript: null,
- headers: null,
- ),
- completion(isTrue));
- });
-
- testWidgets('launching a "mailto" returns true', (WidgetTester _) async {
- expect(
- plugin.launch(
- 'mailto:name@mydomain.com',
- useSafariVC: null,
- useWebView: null,
- universalLinksOnly: null,
- enableDomStorage: null,
- enableJavaScript: null,
- headers: null,
- ),
- completion(isTrue));
- });
-
- testWidgets('launching a "tel" returns true', (WidgetTester _) async {
- expect(
- plugin.launch(
- 'tel:5551234567',
- useSafariVC: null,
- useWebView: null,
- universalLinksOnly: null,
- enableDomStorage: null,
- enableJavaScript: null,
- headers: null,
- ),
- completion(isTrue));
- });
-
- testWidgets('launching a "sms" returns true', (WidgetTester _) async {
- expect(
- plugin.launch(
- 'sms:+19725551212?body=hello%20there',
- useSafariVC: null,
- useWebView: null,
- universalLinksOnly: null,
- enableDomStorage: null,
- enableJavaScript: null,
- headers: null,
- ),
- completion(isTrue));
- });
- });
-
- group('openNewWindow', () {
- testWidgets('http urls should be launched in a new window',
- (WidgetTester _) async {
- plugin.openNewWindow('http://www.google.com');
-
- verify(mockWindow.open('http://www.google.com', ''));
- });
-
- testWidgets('https urls should be launched in a new window',
- (WidgetTester _) async {
- plugin.openNewWindow('https://www.google.com');
-
- verify(mockWindow.open('https://www.google.com', ''));
- });
-
- testWidgets('mailto urls should be launched on a new window',
- (WidgetTester _) async {
- plugin.openNewWindow('mailto:name@mydomain.com');
-
- verify(mockWindow.open('mailto:name@mydomain.com', ''));
- });
-
- testWidgets('tel urls should be launched on a new window',
- (WidgetTester _) async {
- plugin.openNewWindow('tel:5551234567');
-
- verify(mockWindow.open('tel:5551234567', ''));
- });
-
- testWidgets('sms urls should be launched on a new window',
- (WidgetTester _) async {
- plugin.openNewWindow('sms:+19725551212?body=hello%20there');
-
- verify(mockWindow.open('sms:+19725551212?body=hello%20there', ''));
- });
- testWidgets(
- 'setting webOnlyLinkTarget as _self opens the url in the same tab',
- (WidgetTester _) async {
- plugin.openNewWindow('https://www.google.com',
- webOnlyWindowName: '_self');
- verify(mockWindow.open('https://www.google.com', '_self'));
- });
-
- testWidgets(
- 'setting webOnlyLinkTarget as _blank opens the url in a new tab',
- (WidgetTester _) async {
- plugin.openNewWindow('https://www.google.com',
- webOnlyWindowName: '_blank');
- verify(mockWindow.open('https://www.google.com', '_blank'));
- });
-
- group('Safari', () {
- setUp(() {
- when(mockNavigator.vendor).thenReturn('Apple Computer, Inc.');
- when(mockNavigator.appVersion).thenReturn(
- '5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15');
- // Recreate the plugin, so it grabs the overrides from this group
- plugin = UrlLauncherPlugin(debugWindow: mockWindow);
- });
-
- testWidgets('http urls should be launched in a new window',
- (WidgetTester _) async {
- plugin.openNewWindow('http://www.google.com');
-
- verify(mockWindow.open('http://www.google.com', ''));
- });
-
- testWidgets('https urls should be launched in a new window',
- (WidgetTester _) async {
- plugin.openNewWindow('https://www.google.com');
-
- verify(mockWindow.open('https://www.google.com', ''));
- });
-
- testWidgets('mailto urls should be launched on the same window',
- (WidgetTester _) async {
- plugin.openNewWindow('mailto:name@mydomain.com');
-
- verify(mockWindow.open('mailto:name@mydomain.com', '_top'));
- });
-
- testWidgets('tel urls should be launched on the same window',
- (WidgetTester _) async {
- plugin.openNewWindow('tel:5551234567');
-
- verify(mockWindow.open('tel:5551234567', '_top'));
- });
-
- testWidgets('sms urls should be launched on the same window',
- (WidgetTester _) async {
- plugin.openNewWindow('sms:+19725551212?body=hello%20there');
-
- verify(
- mockWindow.open('sms:+19725551212?body=hello%20there', '_top'));
- });
- testWidgets(
- 'mailto urls should use _blank if webOnlyWindowName is set as _blank',
- (WidgetTester _) async {
- plugin.openNewWindow('mailto:name@mydomain.com',
- webOnlyWindowName: '_blank');
- verify(mockWindow.open('mailto:name@mydomain.com', '_blank'));
- });
- });
- });
- });
-
- group('link', () {
- testWidgets('creates anchor with correct attributes',
- (WidgetTester tester) async {
- final Uri uri = Uri.parse('http://foobar/example?q=1');
- await tester.pumpWidget(Directionality(
- textDirection: TextDirection.ltr,
- child: WebLinkDelegate(TestLinkInfo(
- uri: uri,
- target: LinkTarget.blank,
- builder: (BuildContext context, FollowLink followLink) {
- return Container(width: 100, height: 100);
- },
- )),
- ));
- // Platform view creation happens asynchronously.
- await tester.pumpAndSettle();
-
- final html.Element anchor = _findSingleAnchor();
- expect(anchor.getAttribute('href'), uri.toString());
- expect(anchor.getAttribute('target'), '_blank');
-
- final Uri uri2 = Uri.parse('http://foobar2/example?q=2');
- await tester.pumpWidget(Directionality(
- textDirection: TextDirection.ltr,
- child: WebLinkDelegate(TestLinkInfo(
- uri: uri2,
- target: LinkTarget.self,
- builder: (BuildContext context, FollowLink followLink) {
- return Container(width: 100, height: 100);
- },
- )),
- ));
- await tester.pumpAndSettle();
-
- // Check that the same anchor has been updated.
- expect(anchor.getAttribute('href'), uri2.toString());
- expect(anchor.getAttribute('target'), '_self');
- });
-
- testWidgets('sizes itself correctly', (WidgetTester tester) async {
- final Key containerKey = GlobalKey();
- final Uri uri = Uri.parse('http://foobar');
- await tester.pumpWidget(Directionality(
- textDirection: TextDirection.ltr,
- child: Center(
- child: ConstrainedBox(
- constraints: BoxConstraints.tight(Size(100.0, 100.0)),
- child: WebLinkDelegate(TestLinkInfo(
- uri: uri,
- target: LinkTarget.blank,
- builder: (BuildContext context, FollowLink followLink) {
- return Container(
- key: containerKey,
- child: SizedBox(width: 50.0, height: 50.0),
- );
- },
- )),
- ),
- ),
- ));
- await tester.pumpAndSettle();
-
- final Size containerSize = tester.getSize(find.byKey(containerKey));
- // The Stack widget inserted by the `WebLinkDelegate` shouldn't loosen the
- // constraints before passing them to the inner container. So the inner
- // container should respect the tight constraints given by the ancestor
- // `ConstrainedBox` widget.
- expect(containerSize.width, 100.0);
- expect(containerSize.height, 100.0);
- });
- });
-}
-
-html.Element _findSingleAnchor() {
- final List<html.Element> foundAnchors = <html.Element>[];
- for (final html.Element anchor in html.document.querySelectorAll('a')) {
- if (hasProperty(anchor, linkViewIdProperty)) {
- foundAnchors.add(anchor);
- }
- }
-
- // Search inside platform views with shadow roots as well.
- for (final html.Element platformView
- in html.document.querySelectorAll('flt-platform-view')) {
- final html.ShadowRoot shadowRoot = platformView.shadowRoot;
- if (shadowRoot != null) {
- for (final html.Element anchor in shadowRoot.querySelectorAll('a')) {
- if (hasProperty(anchor, linkViewIdProperty)) {
- foundAnchors.add(anchor);
- }
- }
- }
- }
-
- return foundAnchors.single;
-}
-
-class TestLinkInfo extends LinkInfo {
- @override
- final LinkWidgetBuilder builder;
-
- @override
- final Uri uri;
-
- @override
- final LinkTarget target;
-
- @override
- bool get isDisabled => uri == null;
-
- TestLinkInfo({
- @required this.uri,
- @required this.target,
- @required this.builder,
- });
-}
diff --git a/packages/url_launcher/url_launcher_web/test/tests_exist_elsewhere_test.dart b/packages/url_launcher/url_launcher_web/test/tests_exist_elsewhere_test.dart
new file mode 100644
index 0000000..334f521
--- /dev/null
+++ b/packages/url_launcher/url_launcher_web/test/tests_exist_elsewhere_test.dart
@@ -0,0 +1,10 @@
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ test('Tell the user where to find the real tests', () {
+ print('---');
+ print('This package uses integration_test for its tests.');
+ print('See `example/README.md` for more info.');
+ print('---');
+ });
+}