Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

[url_launcher_web] Migrate to null-safety #3522

Merged
merged 21 commits into from
Feb 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice 👏

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.
Comment on lines +1 to +3
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(This file is split from the old url_launcher_web_test)


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