diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..e7af801 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,9 @@ +# Set update schedule for GitHub Actions + +version: 2 +updates: + +- package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index f2baf31..b6afb61 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -18,16 +18,17 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - sdk: [2.12.0, dev] + sdk: [2.17.0, dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - run: dart pub get id: install + - run: dart format --output=none --set-exit-if-changed . - run: dart analyze --fatal-infos - name: Run Xvfb diff --git a/CHANGELOG.md b/CHANGELOG.md index f014ae2..8befbbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.1.2-dev + +- Require Dart 2.17 + ## 1.1.1 - Populate the pubspec `repository` field. diff --git a/analysis_options.yaml b/analysis_options.yaml index 87eecf1..4a111f3 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,19 +1,55 @@ +# https://dart.dev/guides/language/analysis-options include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true + strict-inference: true + strict-raw-types: true linter: rules: - always_declare_return_types + - avoid_bool_literals_in_conditional_expressions + - avoid_catching_errors + - avoid_classes_with_only_static_members - avoid_dynamic_calls + - avoid_private_typedef_functions + - avoid_redundant_argument_values + - avoid_returning_null_for_future + - avoid_returning_this - avoid_unused_constructor_parameters + - avoid_void_async - cancel_subscriptions + - comment_references - directives_ordering + - join_return_with_assignment + - lines_longer_than_80_chars + - literal_only_boolean_expressions + - missing_whitespace_between_adjacent_strings + - no_adjacent_strings_in_list + - no_runtimeType_toString - omit_local_variable_types + - only_throw_errors - package_api_docs + - prefer_asserts_in_initializer_lists + - prefer_const_constructors + - prefer_const_declarations + - prefer_expression_function_bodies + - prefer_final_locals + - prefer_relative_imports - prefer_single_quotes + - require_trailing_commas + - sort_pub_dependencies - test_types_in_equals - throw_in_finally + - type_annotate_public_apis - unawaited_futures + - unnecessary_lambdas + - unnecessary_parenthesis + - unnecessary_raw_strings + - unnecessary_statements + - use_if_null_to_convert_nulls_to_bools + - use_raw_strings + - use_string_buffers + - use_super_parameters diff --git a/example/main.dart b/example/main.dart index a586de4..86b4eea 100644 --- a/example/main.dart +++ b/example/main.dart @@ -10,7 +10,7 @@ Future main() async { print('launched Chrome'); // Pause briefly before opening Chrome with a debug port. - await Future.delayed(Duration(seconds: 3)); + await Future.delayed(const Duration(seconds: 3)); // Launches a chrome browser open to [_googleUrl]. Since we are launching with // a debug port, we will use a variety of different launch configurations, @@ -20,7 +20,7 @@ Future main() async { // When running this dart code, observe that the browser stays open for 3 // seconds before we close it. - await Future.delayed(Duration(seconds: 3)); + await Future.delayed(const Duration(seconds: 3)); await chrome.close(); print('closed Chrome'); diff --git a/lib/src/chrome.dart b/lib/src/chrome.dart index ed6673e..5fea228 100644 --- a/lib/src/chrome.dart +++ b/lib/src/chrome.dart @@ -30,11 +30,14 @@ String get _executable { Platform.environment['PROGRAMFILES(X86)'] ]; return p.join( - windowsPrefixes.firstWhere((prefix) { - if (prefix == null) return false; - final path = p.join(prefix, _windowsExecutable); - return File(path).existsSync(); - }, orElse: () => '.')!, + windowsPrefixes.firstWhere( + (prefix) { + if (prefix == null) return false; + final path = p.join(prefix, _windowsExecutable); + return File(path).existsSync(); + }, + orElse: () => '.', + )!, _windowsExecutable, ); } @@ -114,28 +117,31 @@ class Chrome { final process = await _startProcess(urls, args: args); // Wait until the DevTools are listening before trying to connect. - var _errorLines = []; + final errorLines = []; try { await process.stderr .transform(utf8.decoder) .transform(const LineSplitter()) .firstWhere((line) { - _errorLines.add(line); + errorLines.add(line); return line.startsWith('DevTools listening'); - }).timeout(Duration(seconds: 60)); + }).timeout(const Duration(seconds: 60)); } catch (_) { - throw Exception('Unable to connect to Chrome DevTools.\n\n' - 'Chrome STDERR:\n' + - _errorLines.join('\n')); + throw Exception( + 'Unable to connect to Chrome DevTools.\n\n' + 'Chrome STDERR:\n${errorLines.join('\n')}', + ); } - return _connect(Chrome._( - port, - ChromeConnection('localhost', port), - process: process, - dataDir: dataDir, - deleteDataDir: userDataDir == null, - )); + return _connect( + Chrome._( + port, + ChromeConnection('localhost', port), + process: process, + dataDir: dataDir, + deleteDataDir: userDataDir == null, + ), + ); } /// Starts Chrome with the given arguments. @@ -144,9 +150,8 @@ class Chrome { static Future start( List urls, { List args = const [], - }) async { - return await _startProcess(urls, args: args); - } + }) async => + await _startProcess(urls, args: args); static Future _startProcess( List urls, { @@ -164,7 +169,8 @@ class Chrome { } catch (e) { await chrome.close(); throw ChromeError( - 'Unable to connect to Chrome debug port: ${chrome.debugPort}\n $e'); + 'Unable to connect to Chrome debug port: ${chrome.debugPort}\n $e', + ); } return chrome; } @@ -178,7 +184,7 @@ class Chrome { // profile information. Give it some time before attempting to delete // the directory. if (deleteDataDir) { - await Future.delayed(Duration(milliseconds: 500)); + await Future.delayed(const Duration(milliseconds: 500)); await _dataDir?.delete(recursive: true); } } catch (_) { diff --git a/pubspec.yaml b/pubspec.yaml index 549d942..83dbe54 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,15 +1,15 @@ name: browser_launcher -version: 1.1.1 +version: 1.1.2-dev description: Provides a standardized way to launch web browsers for testing and tools. repository: https://github.com/dart-lang/browser_launcher environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.17.0 <3.0.0' dependencies: path: ^1.8.0 webkit_inspection_protocol: ^1.0.0 dev_dependencies: - lints: ^1.0.0 + lints: ^2.0.0 test: ^1.17.3 diff --git a/test/chrome_test.dart b/test/chrome_test.dart index be87d53..df8ca47 100644 --- a/test/chrome_test.dart +++ b/test/chrome_test.dart @@ -14,7 +14,8 @@ void main() { Chrome? chrome; Future connectToTab(String url) async { - var tab = await chrome!.chromeConnection.getTab((t) => t.url.contains(url)); + final tab = + await chrome!.chromeConnection.getTab((t) => t.url.contains(url)); expect(tab, isNotNull); return tab!.connect(); } @@ -23,10 +24,17 @@ void main() { await chrome!.chromeConnection.getUrl(_openTabUrl(url)); } - Future launchChromeWithDebugPort( - {int port = 0, String? userDataDir, bool signIn = false}) async { - chrome = await Chrome.startWithDebugPort([_googleUrl], - debugPort: port, userDataDir: userDataDir, signIn: signIn); + Future launchChromeWithDebugPort({ + int port = 0, + String? userDataDir, + bool signIn = false, + }) async { + chrome = await Chrome.startWithDebugPort( + [_googleUrl], + debugPort: port, + userDataDir: userDataDir, + signIn: signIn, + ); } Future launchChrome() async { @@ -51,20 +59,23 @@ void main() { test('has a working debugger', () async { await launchChromeWithDebugPort(); - var tabs = await chrome!.chromeConnection.getTabs(); + final tabs = await chrome!.chromeConnection.getTabs(); expect( - tabs, - contains(const TypeMatcher() - .having((t) => t.url, 'url', _googleUrl))); + tabs, + contains( + const TypeMatcher() + .having((t) => t.url, 'url', _googleUrl), + ), + ); }); test('uses open debug port if provided port is 0', () async { - await launchChromeWithDebugPort(port: 0); + await launchChromeWithDebugPort(); expect(chrome!.debugPort, isNot(equals(0))); }); test('can provide a specific debug port', () async { - var port = await findUnusedPort(); + final port = await findUnusedPort(); await launchChromeWithDebugPort(port: port); expect(chrome!.debugPort, port); }); @@ -87,7 +98,7 @@ void main() { while (true) { try { attempts++; - await Future.delayed(const Duration(milliseconds: 100)); + await Future.delayed(const Duration(milliseconds: 100)); dataDir.deleteSync(recursive: true); break; } catch (_) { @@ -98,28 +109,39 @@ void main() { test('can launch with debug port', () async { await launchChromeWithDebugPort( - userDataDir: dataDir.path, signIn: signIn); + userDataDir: dataDir.path, + signIn: signIn, + ); expect(chrome, isNotNull); }); test('has a working debugger', () async { await launchChromeWithDebugPort( - userDataDir: dataDir.path, signIn: signIn); - var tabs = await chrome!.chromeConnection.getTabs(); + userDataDir: dataDir.path, + signIn: signIn, + ); + final tabs = await chrome!.chromeConnection.getTabs(); expect( - tabs, - contains(const TypeMatcher() - .having((t) => t.url, 'url', _googleUrl))); + tabs, + contains( + const TypeMatcher() + .having((t) => t.url, 'url', _googleUrl), + ), + ); }); test('has correct profile path', () async { await launchChromeWithDebugPort( - userDataDir: dataDir.path, signIn: signIn); + userDataDir: dataDir.path, + signIn: signIn, + ); await openTab(_chromeVersionUrl); - var wipConnection = await connectToTab(_chromeVersionUrl); - var result = await _evaluateExpression(wipConnection.page, - "document.getElementById('profile_path').textContent"); + final wipConnection = await connectToTab(_chromeVersionUrl); + final result = await _evaluateExpression( + wipConnection.page, + "document.getElementById('profile_path').textContent", + ); expect(result, contains(_userDataDirName)); }); @@ -133,13 +155,13 @@ String _openTabUrl(String url) => '/json/new?$url'; Future _evaluateExpression(WipPage page, String expression) async { var result = ''; while (result.isEmpty) { - await Future.delayed(Duration(milliseconds: 100)); - var wipResponse = await page.sendCommand( + await Future.delayed(const Duration(milliseconds: 100)); + final wipResponse = await page.sendCommand( 'Runtime.evaluate', params: {'expression': expression}, ); - var response = wipResponse.json['result'] as Map; - var value = (response['result'] as Map)['value']; + final response = wipResponse.json['result'] as Map; + final value = (response['result'] as Map)['value']; result = (value != null && value is String) ? value : ''; } return result;