-
Notifications
You must be signed in to change notification settings - Fork 147
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(shorebird_cli): add login command (#24)
- Loading branch information
Showing
4 changed files
with
139 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export 'login_command.dart'; | ||
export 'publish_command.dart'; | ||
export 'update_command.dart'; |
50 changes: 50 additions & 0 deletions
50
packages/shorebird_cli/lib/src/commands/login_command.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import 'package:args/command_runner.dart'; | ||
import 'package:mason_logger/mason_logger.dart'; | ||
import 'package:shorebird_cli/src/auth/auth.dart'; | ||
|
||
/// {@template login_command} | ||
/// | ||
/// `shorebird login` | ||
/// Login as a new Shorebird user. | ||
/// {@endtemplate} | ||
class LoginCommand extends Command<int> { | ||
/// {@macro login_command} | ||
LoginCommand({required Auth auth, required Logger logger}) | ||
: _auth = auth, | ||
_logger = logger; | ||
|
||
@override | ||
String get description => 'Login as a new Shorebird user.'; | ||
|
||
@override | ||
String get name => 'login'; | ||
|
||
final Auth _auth; | ||
final Logger _logger; | ||
|
||
@override | ||
Future<int> run() async { | ||
final session = _auth.currentSession; | ||
if (session != null) { | ||
_logger | ||
..info('You are already logged in.') | ||
..info("Run 'shorebird logout' to log out and try again."); | ||
return ExitCode.success.code; | ||
} | ||
|
||
final apiKey = _logger.prompt( | ||
'${lightGreen.wrap('?')} Please enter your API Key:', | ||
); | ||
final loginProgress = _logger.progress('Logging into shorebird.dev'); | ||
try { | ||
_auth.login(projectId: 'example', apiKey: apiKey); | ||
loginProgress.complete(); | ||
_logger.success('You are now logged in.'); | ||
return ExitCode.success.code; | ||
} catch (error) { | ||
loginProgress.fail(); | ||
_logger.err(error.toString()); | ||
return ExitCode.software.code; | ||
} | ||
} | ||
} |
87 changes: 87 additions & 0 deletions
87
packages/shorebird_cli/test/src/commands/login_command_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import 'package:mason_logger/mason_logger.dart'; | ||
import 'package:mocktail/mocktail.dart'; | ||
import 'package:shorebird_cli/src/auth/auth.dart'; | ||
import 'package:shorebird_cli/src/auth/session.dart'; | ||
import 'package:shorebird_cli/src/commands/login_command.dart'; | ||
import 'package:test/test.dart'; | ||
|
||
class _MockAuth extends Mock implements Auth {} | ||
|
||
class _MockLogger extends Mock implements Logger {} | ||
|
||
class _MockProgress extends Mock implements Progress {} | ||
|
||
void main() { | ||
group('LoginCommand', () { | ||
const apiKey = 'test-api-key'; | ||
const projectId = 'example'; | ||
const session = Session(apiKey: apiKey, projectId: projectId); | ||
|
||
late Logger logger; | ||
late Auth auth; | ||
late LoginCommand loginCommand; | ||
|
||
setUp(() { | ||
logger = _MockLogger(); | ||
auth = _MockAuth(); | ||
loginCommand = LoginCommand(auth: auth, logger: logger); | ||
|
||
when(() => logger.progress(any())).thenReturn(_MockProgress()); | ||
}); | ||
|
||
test('exits with code 0 when already logged in', () async { | ||
when(() => auth.currentSession).thenReturn(session); | ||
|
||
final result = await loginCommand.run(); | ||
expect(result, equals(ExitCode.success.code)); | ||
|
||
verify(() => logger.info('You are already logged in.')).called(1); | ||
verify( | ||
() => logger.info("Run 'shorebird logout' to log out and try again."), | ||
).called(1); | ||
}); | ||
|
||
test('exits with code 70 when error occurs', () async { | ||
final error = Exception('oops something went wrong!'); | ||
when(() => logger.prompt(any())).thenReturn(apiKey); | ||
when(() => auth.currentSession).thenReturn(null); | ||
when( | ||
() => auth.login( | ||
apiKey: any(named: 'apiKey'), | ||
projectId: any(named: 'projectId'), | ||
), | ||
).thenThrow(error); | ||
|
||
final result = await loginCommand.run(); | ||
expect(result, equals(ExitCode.software.code)); | ||
|
||
verify(() => logger.progress('Logging into shorebird.dev')).called(1); | ||
verify( | ||
() => auth.login(apiKey: apiKey, projectId: projectId), | ||
).called(1); | ||
verify(() => logger.err(error.toString())).called(1); | ||
}); | ||
|
||
test('exits with code 0 when logged in successfully', () async { | ||
when(() => logger.prompt(any())).thenReturn(apiKey); | ||
when(() => auth.currentSession).thenReturn(null); | ||
when( | ||
() => auth.login( | ||
apiKey: any(named: 'apiKey'), | ||
projectId: any(named: 'projectId'), | ||
), | ||
).thenAnswer((_) async {}); | ||
|
||
final result = await loginCommand.run(); | ||
expect(result, equals(ExitCode.success.code)); | ||
|
||
verify(() => logger.progress('Logging into shorebird.dev')).called(1); | ||
verify( | ||
() => auth.login(apiKey: apiKey, projectId: projectId), | ||
).called(1); | ||
verify( | ||
() => logger.success('You are now logged in.'), | ||
).called(1); | ||
}); | ||
}); | ||
} |