blob: bfa94821e41af22d33b23b00e3860807a7d512ce [file] [log] [blame]
// 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,
});
}