Skip to content

Commit e8585d6

Browse files
authored
feat: add optional auto-install (#29)
1 parent 0ecc8ea commit e8585d6

File tree

2 files changed

+72
-21
lines changed

2 files changed

+72
-21
lines changed

lib/src/command_runner/completion_command_runner.dart

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ abstract class CompletionCommandRunner<T> extends CommandRunner<T> {
4242

4343
CompletionInstallation? _completionInstallation;
4444

45+
/// Define whether the installation of the completion files should done
46+
/// automatically upon the first command run.
47+
///
48+
/// If set to false the user will have to manually install the completion
49+
/// files via the `install-completion-files` command.
50+
///
51+
/// Override this field to disable auto installation.
52+
bool get enableAutoInstall => true;
53+
4554
/// The [CompletionInstallation] used to install completion files.
4655
CompletionInstallation get completionInstallation {
4756
var completionInstallation = _completionInstallation;
@@ -62,7 +71,8 @@ abstract class CompletionCommandRunner<T> extends CommandRunner<T> {
6271
InstallCompletionFilesCommand.commandName,
6372
];
6473

65-
if (!reservedCommands.contains(topLevelResults.command?.name)) {
74+
if (enableAutoInstall &&
75+
!reservedCommands.contains(topLevelResults.command?.name)) {
6676
// When auto installing, use error level to display messages.
6777
tryInstallCompletionFiles(Level.error);
6878
}
@@ -77,6 +87,8 @@ abstract class CompletionCommandRunner<T> extends CommandRunner<T> {
7787
completionInstallationLogger.level = level;
7888
completionInstallation.install(executableName);
7989
} on CompletionInstallationException catch (e) {
90+
completionInstallationLogger.warn(e.toString());
91+
} on Exception catch (e) {
8092
completionInstallationLogger.err(e.toString());
8193
}
8294
}

test/src/command_runner/completion_command_runner_test.dart

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ class MockCompletionInstallation extends Mock
1414
class _TestCompletionCommandRunner extends CompletionCommandRunner<int> {
1515
_TestCompletionCommandRunner() : super('test', 'Test command runner');
1616

17+
@override
18+
bool enableAutoInstall = true;
19+
1720
@override
1821
// ignore: overridden_fields
1922
final Logger completionLogger = MockLogger();
@@ -52,6 +55,10 @@ class _TestCompletionResult extends CompletionResult {
5255
}
5356

5457
void main() {
58+
setUpAll(() {
59+
registerFallbackValue(Level.error);
60+
});
61+
5562
group('CompletionCommandRunner', () {
5663
test('can be instantiated', () {
5764
final commandRunner = _TestCompletionCommandRunner();
@@ -105,40 +112,72 @@ void main() {
105112
);
106113
});
107114

108-
test('Tries to install completion file test subcommand', () async {
109-
final commandRunner = _TestCompletionCommandRunner()
110-
..addCommand(_TestUserCommand())
111-
..mockCompletionInstallation = MockCompletionInstallation();
115+
group('auto install', () {
116+
test('Tries to install completion files on test subcommand', () async {
117+
final commandRunner = _TestCompletionCommandRunner()
118+
..addCommand(_TestUserCommand())
119+
..mockCompletionInstallation = MockCompletionInstallation();
112120

113-
await commandRunner.run(['ahoy']);
121+
await commandRunner.run(['ahoy']);
114122

115-
verify(() => commandRunner.completionInstallation.install('test'))
116-
.called(1);
123+
verify(() => commandRunner.completionInstallation.install('test'))
124+
.called(1);
125+
126+
verify(
127+
() => commandRunner.completionInstallationLogger.level = Level.error,
128+
).called(1);
129+
});
130+
131+
test('does not auto install when it is disabled', () async {
132+
final commandRunner = _TestCompletionCommandRunner()
133+
..enableAutoInstall = false
134+
..addCommand(_TestUserCommand())
135+
..mockCompletionInstallation = MockCompletionInstallation();
136+
137+
await commandRunner.run(['ahoy']);
117138

118-
verify(
119-
() => commandRunner.completionInstallationLogger.level = Level.error,
120-
).called(1);
139+
verifyNever(() => commandRunner.completionInstallation.install('test'));
140+
141+
verifyNever(
142+
() => commandRunner.completionInstallationLogger.level = any(),
143+
);
144+
});
121145
});
122146

123-
test('When something goes wrong on install, it logs as error', () async {
147+
test(
148+
'When it throws CompletionInstallationException, it logs as a warning',
149+
() async {
150+
final commandRunner = _TestCompletionCommandRunner()
151+
..addCommand(_TestUserCommand())
152+
..mockCompletionInstallation = MockCompletionInstallation();
153+
154+
when(
155+
() => commandRunner.completionInstallation.install('test'),
156+
).thenThrow(
157+
CompletionInstallationException(message: 'oops', rootCommand: 'test'),
158+
);
159+
160+
await commandRunner.run(['ahoy']);
161+
162+
verify(() => commandRunner.completionInstallationLogger.warn(any()))
163+
.called(1);
164+
},
165+
);
166+
167+
test('When an unknown exception happens during a install, it logs as error',
168+
() async {
124169
final commandRunner = _TestCompletionCommandRunner()
125170
..addCommand(_TestUserCommand())
126171
..mockCompletionInstallation = MockCompletionInstallation();
127172

128173
when(
129174
() => commandRunner.completionInstallation.install('test'),
130-
).thenThrow(
131-
CompletionInstallationException(message: 'oops', rootCommand: 'test'),
132-
);
175+
).thenThrow(Exception('oops'));
133176

134177
await commandRunner.run(['ahoy']);
135178

136-
verify(
137-
() {
138-
commandRunner.completionInstallationLogger
139-
.err('Could not install completion scripts for test: oops');
140-
},
141-
).called(1);
179+
verify(() => commandRunner.completionInstallationLogger.err(any()))
180+
.called(1);
142181
});
143182

144183
group('renderCompletionResult', () {

0 commit comments

Comments
 (0)