diff --git a/packages/url_launcher/url_launcher_web/CHANGELOG.md b/packages/url_launcher/url_launcher_web/CHANGELOG.md index b12189336e74..9dfe504d0be2 100644 --- a/packages/url_launcher/url_launcher_web/CHANGELOG.md +++ b/packages/url_launcher/url_launcher_web/CHANGELOG.md @@ -1,3 +1,8 @@ +# 0.1.4 + +- (Null safety) Remove dependency on `package:platform_detect` +- Port unit tests to run with `flutter drive` + # 0.1.3+2 - Fix a typo in a test name and fix some style inconsistencies. 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 da73cd8b6350..9f1d40dda048 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 @@ -5,19 +5,33 @@ import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'package:meta/meta.dart'; import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; -import 'package:platform_detect/platform_detect.dart' show browser; - const _safariTargetTopSchemes = { 'mailto', 'tel', 'sms', }; +String _getUrlScheme(String url) => Uri.tryParse(url)?.scheme; + +bool _isSafariTargetTopScheme(String url) => + _safariTargetTopSchemes.contains(_getUrlScheme(url)); + +// Taken from package:platform_detect. +bool _navigatorIsSafari(html.Navigator navigator) { + // An web view running in an iOS app does not have a 'Version/X.X.X' string in the appVersion + final vendor = navigator.vendor; + final appVersion = navigator.appVersion; + return vendor != null && + vendor.contains('Apple') && + appVersion != null && + appVersion.contains('Version'); +} /// The web implementation of [UrlLauncherPlatform]. /// /// This class implements the `package:url_launcher` functionality for the web. class UrlLauncherPlugin extends UrlLauncherPlatform { html.Window _window; + bool _isSafari = false; // The set of schemes that can be handled by the plugin static final _supportedSchemes = { @@ -26,19 +40,16 @@ class UrlLauncherPlugin extends UrlLauncherPlatform { }.union(_safariTargetTopSchemes); /// A constructor that allows tests to override the window object used by the plugin. - UrlLauncherPlugin({@visibleForTesting html.Window window}) - : _window = window ?? html.window; + UrlLauncherPlugin({@visibleForTesting html.Window debugWindow}) + : _window = debugWindow ?? html.window { + _isSafari = _navigatorIsSafari(_window.navigator); + } /// Registers this class as the default instance of [UrlLauncherPlatform]. static void registerWith(Registrar registrar) { UrlLauncherPlatform.instance = UrlLauncherPlugin(); } - String _getUrlScheme(String url) => Uri.tryParse(url)?.scheme; - - bool _isSafariTargetTopScheme(String url) => - _safariTargetTopSchemes.contains(_getUrlScheme(url)); - /// Opens the given [url] in the specified [webOnlyWindowName]. /// /// Returns the newly created window. @@ -47,7 +58,7 @@ class UrlLauncherPlugin extends UrlLauncherPlatform { // 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 ?? - ((browser.isSafari && _isSafariTargetTopScheme(url)) ? '_top' : ''); + ((_isSafari && _isSafariTargetTopScheme(url)) ? '_top' : ''); return _window.open(url, target); } diff --git a/packages/url_launcher/url_launcher_web/pubspec.yaml b/packages/url_launcher/url_launcher_web/pubspec.yaml index d206c0f1bbb9..ac5160c181bc 100644 --- a/packages/url_launcher/url_launcher_web/pubspec.yaml +++ b/packages/url_launcher/url_launcher_web/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/flutter/plugins/tree/master/packages/url_launcher/u # 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.3+2 +version: 0.1.4 flutter: plugin: @@ -15,7 +15,6 @@ flutter: dependencies: url_launcher_platform_interface: ^1.0.8 - platform_detect: ^1.4.0 flutter: sdk: flutter flutter_web_plugins: @@ -28,6 +27,8 @@ dev_dependencies: url_launcher: ^5.2.5 pedantic: ^1.8.0 mockito: ^4.1.1 + integration_test: + path: ../../integration_test environment: sdk: ">=2.2.0 <3.0.0" diff --git a/packages/url_launcher/url_launcher_web/test/README.md b/packages/url_launcher/url_launcher_web/test/README.md new file mode 100644 index 000000000000..7c48d024ba57 --- /dev/null +++ b/packages/url_launcher/url_launcher_web/test/README.md @@ -0,0 +1,17 @@ +# Running browser_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: + * + +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` diff --git a/packages/url_launcher/url_launcher_web/test/lib/main.dart b/packages/url_launcher/url_launcher_web/test/lib/main.dart new file mode 100644 index 000000000000..10415204570c --- /dev/null +++ b/packages/url_launcher/url_launcher_web/test/lib/main.dart @@ -0,0 +1,22 @@ +// Copyright 2013 The Flutter 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 'package:flutter/material.dart'; + +void main() { + runApp(MyApp()); +} + +/// App for testing +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State { + @override + Widget build(BuildContext context) { + return Text('Testing... Look at the console output for results!'); + } +} diff --git a/packages/url_launcher/url_launcher_web/test/pubspec.yaml b/packages/url_launcher/url_launcher_web/test/pubspec.yaml new file mode 100644 index 000000000000..e755dff85004 --- /dev/null +++ b/packages/url_launcher/url_launcher_web/test/pubspec.yaml @@ -0,0 +1,22 @@ +name: regular_integration_tests +publish_to: none + +environment: + sdk: ">=2.2.2 <3.0.0" + +dependencies: + flutter: + sdk: flutter + +dev_dependencies: + 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 + diff --git a/packages/url_launcher/url_launcher_web/test/run_test b/packages/url_launcher/url_launcher_web/test/run_test new file mode 100755 index 000000000000..74a8526a0fa3 --- /dev/null +++ b/packages/url_launcher/url_launcher_web/test/run_test @@ -0,0 +1,17 @@ +#!/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/url_launcher_web_test.dart b/packages/url_launcher/url_launcher_web/test/test_driver/url_launcher_web_integration.dart similarity index 59% rename from packages/url_launcher/url_launcher_web/test/url_launcher_web_test.dart rename to packages/url_launcher/url_launcher_web/test/test_driver/url_launcher_web_integration.dart index 56f23a464f1d..d0dd6e38ee46 100644 --- a/packages/url_launcher/url_launcher_web/test/url_launcher_web_test.dart +++ b/packages/url_launcher/url_launcher_web/test/test_driver/url_launcher_web_integration.dart @@ -2,45 +2,53 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -@TestOn('chrome') // Uses web-only Flutter SDK - import 'dart:html' as html; import 'package:flutter_test/flutter_test.dart'; import 'package:url_launcher_web/url_launcher_web.dart'; import 'package:mockito/mockito.dart'; +import 'package:integration_test/integration_test.dart'; -import 'package:platform_detect/test_utils.dart' as platform; +class _MockWindow extends Mock implements html.Window {} -class MockWindow extends Mock implements html.Window {} +class _MockNavigator extends Mock implements html.Navigator {} void main() { - group('$UrlLauncherPlugin', () { - MockWindow mockWindow = MockWindow(); - UrlLauncherPlugin plugin = UrlLauncherPlugin(window: mockWindow); + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + group('UrlLauncherPlugin', () { + _MockWindow mockWindow; + _MockNavigator mockNavigator; + + UrlLauncherPlugin plugin; setUp(() { - platform.configurePlatformForTesting(browser: platform.chrome); + mockWindow = _MockWindow(); + mockNavigator = _MockNavigator(); + when(mockWindow.navigator).thenReturn(mockNavigator); + + plugin = UrlLauncherPlugin(debugWindow: mockWindow); }); group('canLaunch', () { - test('"http" URLs -> true', () { + testWidgets('"http" URLs -> true', (WidgetTester _) async { expect(plugin.canLaunch('http://google.com'), completion(isTrue)); }); - test('"https" URLs -> true', () { - expect(plugin.canLaunch('https://google.com'), completion(isTrue)); + testWidgets('"https" URLs -> true', (WidgetTester _) async { + expect( + plugin.canLaunch('https://go, (Widogle.com'), completion(isTrue)); }); - test('"mailto" URLs -> true', () { + testWidgets('"mailto" URLs -> true', (WidgetTester _) async { expect( plugin.canLaunch('mailto:name@mydomain.com'), completion(isTrue)); }); - test('"tel" URLs -> true', () { + testWidgets('"tel" URLs -> true', (WidgetTester _) async { expect(plugin.canLaunch('tel:5551234567'), completion(isTrue)); }); - test('"sms" URLs -> true', () { + testWidgets('"sms" URLs -> true', (WidgetTester _) async { expect(plugin.canLaunch('sms:+19725551212?body=hello%20there'), completion(isTrue)); }); @@ -50,15 +58,15 @@ void main() { setUp(() { // Simulate that window.open does something. when(mockWindow.open('https://www.google.com', '')) - .thenReturn(MockWindow()); + .thenReturn(_MockWindow()); when(mockWindow.open('mailto:name@mydomain.com', '')) - .thenReturn(MockWindow()); - when(mockWindow.open('tel:5551234567', '')).thenReturn(MockWindow()); + .thenReturn(_MockWindow()); + when(mockWindow.open('tel:5551234567', '')).thenReturn(_MockWindow()); when(mockWindow.open('sms:+19725551212?body=hello%20there', '')) - .thenReturn(MockWindow()); + .thenReturn(_MockWindow()); }); - test('launching a URL returns true', () { + testWidgets('launching a URL returns true', (WidgetTester _) async { expect( plugin.launch( 'https://www.google.com', @@ -72,7 +80,7 @@ void main() { completion(isTrue)); }); - test('launching a "mailto" returns true', () { + testWidgets('launching a "mailto" returns true', (WidgetTester _) async { expect( plugin.launch( 'mailto:name@mydomain.com', @@ -86,7 +94,7 @@ void main() { completion(isTrue)); }); - test('launching a "tel" returns true', () { + testWidgets('launching a "tel" returns true', (WidgetTester _) async { expect( plugin.launch( 'tel:5551234567', @@ -100,7 +108,7 @@ void main() { completion(isTrue)); }); - test('launching a "sms" returns true', () { + testWidgets('launching a "sms" returns true', (WidgetTester _) async { expect( plugin.launch( 'sms:+19725551212?body=hello%20there', @@ -116,44 +124,51 @@ void main() { }); group('openNewWindow', () { - test('http urls should be launched in a new window', () { + 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', '')); }); - test('https urls should be launched in a new window', () { + 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', '')); }); - test('mailto urls should be launched on a new window', () { + 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', '')); }); - test('tel urls should be launched on a new window', () { + testWidgets('tel urls should be launched on a new window', + (WidgetTester _) async { plugin.openNewWindow('tel:5551234567'); verify(mockWindow.open('tel:5551234567', '')); }); - test('sms urls should be launched on a new window', () { + 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', '')); }); - test('setting webOnlyLinkTarget as _self opens the url in the same tab', - () { + 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')); }); - test('setting webOnlyLinkTarget as _blank opens the url in a new tab', - () { + 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')); @@ -161,42 +176,51 @@ void main() { group('Safari', () { setUp(() { - platform.configurePlatformForTesting(browser: platform.safari); + 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); }); - test('http urls should be launched in a new window', () { + 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', '')); }); - test('https urls should be launched in a new window', () { + 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', '')); }); - test('mailto urls should be launched on the same window', () { + 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')); }); - test('tel urls should be launched on the same window', () { + testWidgets('tel urls should be launched on the same window', + (WidgetTester _) async { plugin.openNewWindow('tel:5551234567'); verify(mockWindow.open('tel:5551234567', '_top')); }); - test('sms urls should be launched on the same window', () { + 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')); }); - test( + 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/test/test_driver/url_launcher_web_integration_test.dart b/packages/url_launcher/url_launcher_web/test/test_driver/url_launcher_web_integration_test.dart new file mode 100644 index 000000000000..64e2248a4f9b --- /dev/null +++ b/packages/url_launcher/url_launcher_web/test/test_driver/url_launcher_web_integration_test.dart @@ -0,0 +1,7 @@ +// 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 'package:integration_test/integration_test_driver.dart'; + +Future main() async => integrationDriver(); diff --git a/packages/url_launcher/url_launcher_web/test/web/index.html b/packages/url_launcher/url_launcher_web/test/web/index.html new file mode 100644 index 000000000000..dc8d0cfe0428 --- /dev/null +++ b/packages/url_launcher/url_launcher_web/test/web/index.html @@ -0,0 +1,12 @@ + + + + + Browser Tests + + + + +