diff --git a/packages/shorebird_code_push_client/lib/src/code_push_client.dart b/packages/shorebird_code_push_client/lib/src/code_push_client.dart index a052c7e2..d703bb17 100644 --- a/packages/shorebird_code_push_client/lib/src/code_push_client.dart +++ b/packages/shorebird_code_push_client/lib/src/code_push_client.dart @@ -194,6 +194,25 @@ class CodePushClient { .toList(); } + /// List all channels for the provided [appId]. + Future> getChannels({required String appId}) async { + final response = await _httpClient.get( + Uri.parse('$hostedUri/api/v1/channels').replace( + queryParameters: {'appId': appId}, + ), + headers: _apiKeyHeader, + ); + + if (response.statusCode != HttpStatus.ok) { + throw _parseErrorResponse(response.body); + } + + final channels = json.decode(response.body) as List; + return channels + .map((channel) => Channel.fromJson(channel as Map)) + .toList(); + } + /// List all release for the provided [appId]. Future> getReleases({required String appId}) async { final response = await _httpClient.get( diff --git a/packages/shorebird_code_push_client/test/src/code_push_client_test.dart b/packages/shorebird_code_push_client/test/src/code_push_client_test.dart index 147e8c1b..2af766ad 100644 --- a/packages/shorebird_code_push_client/test/src/code_push_client_test.dart +++ b/packages/shorebird_code_push_client/test/src/code_push_client_test.dart @@ -756,6 +756,92 @@ void main() { }); }); + group('getChannels', () { + const appId = 'test-app-id'; + test('throws an exception if the http request fails (unknown)', () async { + when( + () => httpClient.get( + any(), + headers: any(named: 'headers'), + ), + ).thenAnswer( + (_) async => http.Response( + '', + HttpStatus.failedDependency, + ), + ); + + expect( + codePushClient.getChannels(appId: appId), + throwsA( + isA().having( + (e) => e.message, + 'message', + CodePushClient.unknownErrorMessage, + ), + ), + ); + }); + + test('throws an exception if the http request fails', () async { + when( + () => httpClient.get( + any(), + headers: any(named: 'headers'), + ), + ).thenAnswer( + (_) async => http.Response( + json.encode(errorResponse.toJson()), + HttpStatus.failedDependency, + ), + ); + + expect( + codePushClient.getChannels(appId: appId), + throwsA( + isA().having( + (e) => e.message, + 'message', + errorResponse.message, + ), + ), + ); + }); + + test('completes when request succeeds (empty)', () async { + when( + () => httpClient.get( + any(), + headers: any(named: 'headers'), + ), + ).thenAnswer( + (_) async => http.Response(json.encode([]), HttpStatus.ok), + ); + + final apps = await codePushClient.getChannels(appId: appId); + expect(apps, isEmpty); + }); + + test('completes when request succeeds (populated)', () async { + final expected = [ + Channel(id: 0, appId: '1', name: 'stable'), + Channel(id: 1, appId: '2', name: 'development'), + ]; + + when( + () => httpClient.get( + any(), + headers: any(named: 'headers'), + ), + ).thenAnswer( + (_) async => http.Response(json.encode(expected), HttpStatus.ok), + ); + + final actual = await codePushClient.getChannels(appId: appId); + expect(json.encode(actual), equals(json.encode(expected))); + }); + }); + group('getReleases', () { const appId = 'test-app-id'; test('throws an exception if the http request fails (unknown)', () async {