From b0825f260b35d70e75fc91a9e715b2022161983a Mon Sep 17 00:00:00 2001 From: Hampus Lavin Date: Mon, 18 Nov 2024 09:53:02 +0100 Subject: [PATCH] fix: report analytics before running command --- .../better_command_runner.dart | 23 +++++++++++++------ .../better_command_runner/analytics_test.dart | 18 +++++++++++++++ test/test_utils.dart | 5 ++++ 3 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 test/test_utils.dart diff --git a/lib/src/better_command_runner/better_command_runner.dart b/lib/src/better_command_runner/better_command_runner.dart index 3d0c8a9..18ea764 100644 --- a/lib/src/better_command_runner/better_command_runner.dart +++ b/lib/src/better_command_runner/better_command_runner.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:args/args.dart'; import 'package:args/command_runner.dart'; import 'package:cli_tools/src/better_command_runner/exit_exception.dart'; @@ -134,14 +136,9 @@ class BetterCommandRunner extends CommandRunner { _onAnalyticsEvent = null; } - await _onBeforeRunCommand?.call(this); - - try { - await super.runCommand(topLevelResults); + unawaited(Future(() async { var command = topLevelResults.command; - if (command == null) { - _onAnalyticsEvent?.call(BetterCommandRunnerAnalyticsEvents.help); - } else { + if (command != null) { // Command name can only be null for top level results. // But since we are taking the name of a command from the top level // results there should always be a name specified. @@ -149,7 +146,19 @@ class BetterCommandRunner extends CommandRunner { _onAnalyticsEvent?.call( command.name ?? BetterCommandRunnerAnalyticsEvents.invalid, ); + return; + } + + var noUnexpectedArgs = topLevelResults.rest.isEmpty; + if (noUnexpectedArgs) { + _onAnalyticsEvent?.call(BetterCommandRunnerAnalyticsEvents.help); } + })); + + await _onBeforeRunCommand?.call(this); + + try { + await super.runCommand(topLevelResults); } on UsageException catch (e) { _logError?.call(e.toString()); _onAnalyticsEvent?.call(BetterCommandRunnerAnalyticsEvents.invalid); diff --git a/test/better_command_runner/analytics_test.dart b/test/better_command_runner/analytics_test.dart index afee6f2..328fb4f 100644 --- a/test/better_command_runner/analytics_test.dart +++ b/test/better_command_runner/analytics_test.dart @@ -2,6 +2,8 @@ import 'package:args/command_runner.dart'; import 'package:cli_tools/better_command_runner.dart'; import 'package:test/test.dart'; +import '../test_utils.dart'; + class MockCommand extends Command { static String commandName = 'mock-command'; @@ -79,6 +81,8 @@ void main() { var args = ['--no-${BetterCommandRunnerFlags.analytics}']; await runner.run(args); + await flushEventQueue(); + expect(runner.analyticsEnabled(), isFalse); }); @@ -92,6 +96,8 @@ void main() { // Ignore any exception } + await flushEventQueue(); + expect(events, hasLength(1)); expect(events.first, equals('invalid')); }); @@ -107,6 +113,8 @@ void main() { // Ignore any exception } + await flushEventQueue(); + expect(events, hasLength(1)); expect(events.first, equals('invalid')); }); @@ -115,6 +123,8 @@ void main() { () async { await runner.run([]); + await flushEventQueue(); + expect(events, hasLength(1)); expect(events.first, equals('help')); }); @@ -124,6 +134,8 @@ void main() { () async { await runner.run(['--${BetterCommandRunnerFlags.analytics}']); + await flushEventQueue(); + expect(events, hasLength(1)); expect(events.first, equals('help')); }); @@ -150,6 +162,8 @@ void main() { await runner.run(args); + await flushEventQueue(); + expect(events, hasLength(1)); expect(events.first, equals(MockCommand.commandName)); }); @@ -161,6 +175,8 @@ void main() { await runner.run(args); + await flushEventQueue(); + expect(events, hasLength(1)); expect(events.first, equals(MockCommand.commandName)); }); @@ -176,6 +192,8 @@ void main() { // Ignore any exception } + await flushEventQueue(); + expect(events, hasLength(1)); expect(events.first, equals('invalid')); }); diff --git a/test/test_utils.dart b/test/test_utils.dart new file mode 100644 index 0000000..e5c0ca7 --- /dev/null +++ b/test/test_utils.dart @@ -0,0 +1,5 @@ +/// Test helper to flush the event queue. +/// Useful for waiting for async events to complete before continuing the test. +Future flushEventQueue() { + return Future.delayed(Duration.zero); +}