Skip to content

Commit

Permalink
[url_launcher_web] Migrate to null-safety (flutter#3522)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
ditman and mvanbeusekom authored Feb 16, 2021
1 parent 7a3b4ae commit 4df0880
Show file tree
Hide file tree
Showing 18 changed files with 956 additions and 261 deletions.
1 change: 1 addition & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ analyzer:
# 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.
Expand Down
4 changes: 4 additions & 0 deletions packages/url_launcher/url_launcher_web/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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).
Expand Down
31 changes: 31 additions & 0 deletions packages/url_launcher/url_launcher_web/example/README.md
Original file line number Diff line number Diff line change
@@ -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.)
6 changes: 6 additions & 0 deletions packages/url_launcher/url_launcher_web/example/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
targets:
$default:
sources:
- integration_test/*.dart
- lib/$lib$
- $package$
Original file line number Diff line number Diff line change
@@ -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,
});
}
Loading

0 comments on commit 4df0880

Please sign in to comment.