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 d6c6f758..8a885fe7 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 @@ -261,6 +261,30 @@ class CodePushClient { .toList(); } + /// Get a release artifact for a specific [releaseId], [arch], and [platform]. + Future getReleaseArtifact({ + required int releaseId, + required String arch, + required String platform, + }) async { + final response = await _httpClient.get( + Uri.parse('$hostedUri/api/v1/releases/$releaseId/artifacts').replace( + queryParameters: { + 'arch': arch, + 'platform': platform, + }, + ), + headers: _apiKeyHeader, + ); + + if (response.statusCode != HttpStatus.ok) { + throw _parseErrorResponse(response.body); + } + + final body = json.decode(response.body) as Map; + return ReleaseArtifact.fromJson(body); + } + /// Promote the [patchId] to the [channelId]. Future promotePatch({ required int patchId, 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 caa2ab01..867a9f3f 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 @@ -1061,6 +1061,98 @@ void main() { }); }); + group('getReleaseArtifact', () { + const releaseId = 0; + const arch = 'aarch64'; + const platform = 'android'; + + 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.getReleaseArtifact( + releaseId: releaseId, + arch: arch, + platform: platform, + ), + 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.getReleaseArtifact( + releaseId: releaseId, + arch: arch, + platform: platform, + ), + throwsA( + isA().having( + (e) => e.message, + 'message', + errorResponse.message, + ), + ), + ); + }); + + test('completes when request succeeds', () async { + final expected = ReleaseArtifact( + id: 0, + releaseId: releaseId, + arch: arch, + platform: platform, + url: 'https://example.com', + hash: '#', + size: 42, + ); + + when( + () => httpClient.get( + any(), + headers: any(named: 'headers'), + ), + ).thenAnswer( + (_) async => http.Response(json.encode(expected), HttpStatus.ok), + ); + + final actual = await codePushClient.getReleaseArtifact( + releaseId: releaseId, + arch: arch, + platform: platform, + ); + expect(json.encode(actual), equals(json.encode(expected))); + }); + }); + group('promotePatch', () { const patchId = 0; const channelId = 0;