Skip to content

Commit

Permalink
Merge pull request #169 from hayribakici/code_cleanup_list
Browse files Browse the repository at this point in the history
Refactors duplicate logic of `list` methods
  • Loading branch information
rinukkusu authored Sep 18, 2023
2 parents 45235db + d82ed83 commit a99c15b
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 53 deletions.
9 changes: 2 additions & 7 deletions lib/src/endpoints/albums.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,8 @@ class Albums extends EndpointPaging {
}

/// Returns album informations about a list of [albumIds]
Future<Iterable<Album>> list(Iterable<String> albumIds) async {
var jsonString = await _get('$_path?ids=${albumIds.join(',')}');
var map = json.decode(jsonString);

var artistsMap = map['albums'] as Iterable<dynamic>;
return artistsMap.map((m) => Album.fromJson(m));
}
Future<Iterable<Album>> list(List<String> albumIds) async => _listWithIds(
path: _path, ids: albumIds, jsonKey: 'albums', fromJson: Album.fromJson);

/// Returns the tracks of a given [albumId]
@Deprecated('Use [tracks] instead')
Expand Down
23 changes: 9 additions & 14 deletions lib/src/endpoints/artists.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,17 @@ class Artists extends EndpointPaging {
relatedArtists(artistId);

/// Retrieves multiple artists with [artistIds]
Future<Iterable<Artist>> list(Iterable<String> artistIds) async {
var jsonString = await _api._get('$_path?ids=${artistIds.join(',')}');
var map = json.decode(jsonString);

var artistsMap = map['artists'] as Iterable<dynamic>;
return artistsMap.map((m) => Artist.fromJson(m));
}
Future<Iterable<Artist>> list(List<String> artistIds) async => _listWithIds(
path: _path,
ids: artistIds,
jsonKey: 'artists',
fromJson: Artist.fromJson);

/// Returns related artists based on the artist with its [artistId]
Future<Iterable<Artist>> relatedArtists(String artistId) async {
var jsonString = await _api._get('$_path/$artistId/related-artists');
var map = json.decode(jsonString);

var artistsMap = map['artists'] as Iterable<dynamic>;
return artistsMap.map((m) => Artist.fromJson(m));
}
Future<Iterable<Artist>> relatedArtists(String artistId) async => _list(
path: '$_path/$artistId/related-artists',
jsonKey: 'artists',
fromJson: Artist.fromJson);

/// [includeGroups] - A comma-separated list of keywords that will be used to
/// filter the response. If not supplied, all album types will be returned.
Expand Down
13 changes: 6 additions & 7 deletions lib/src/endpoints/audio_features.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@ class AudioFeatures extends EndpointBase {
}

/// Retrieve multiple audio features of tracks with [trackIds]
Future<Iterable<AudioFeature>> list(Iterable<String> trackIds) async {
var jsonString = await _api._get('$_path?ids=${trackIds.join(',')}');
var map = json.decode(jsonString);

var artistsMap = map['audio_features'] as Iterable<dynamic>;
return artistsMap.map((m) => AudioFeature.fromJson(m));
}
Future<Iterable<AudioFeature>> list(List<String> trackIds) async =>
_listWithIds(
path: _path,
ids: trackIds,
jsonKey: 'audio_features',
fromJson: AudioFeature.fromJson);
}
30 changes: 30 additions & 0 deletions lib/src/endpoints/endpoint_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,34 @@ abstract class EndpointBase {
'${filteredQuery.keys.toList()[i]}=${filteredQuery.values.toList()[i]}',
).join('&');
}

/// Generic method that requests a set of [T]'s with their given [ids].
Future<Iterable<T>> _listWithIds<T>(
{required String path,
required List<String> ids,
required String jsonKey,
required T Function(Map<String, dynamic>) fromJson,
Map<String, dynamic>? optionalParams}) async {
assert(ids.isNotEmpty, 'No id\'s were provided');

// filling the params
var params = <String, dynamic>{'ids': ids.join(',')};
params.addAll(optionalParams ?? {});

return _list(
path: '$path?${_buildQuery(params)}',
jsonKey: jsonKey,
fromJson: fromJson);
}

/// Generic method that converts requested json arrays into
/// [T] iterables with the given [toJson] function
Future<Iterable<T>> _list<T>(
{required String path,
required String jsonKey,
required T Function(Map<String, dynamic>) fromJson}) async {
var jsonString = await _api._get(path);
final tJson = jsonDecode(jsonString)[jsonKey] as Iterable<dynamic>;
return tJson.map((json) => fromJson(json));
}
}
22 changes: 10 additions & 12 deletions lib/src/endpoints/episodes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,17 @@ class Episodes extends EndpointBase {

Future<EpisodeFull> get(String id, [Market? market]) async {
assert(id.isNotEmpty, 'No episode id was provided');
var jsonString = await _api
._get('$_path/$id?' + _buildQuery({'market': market?.name}));
var jsonString =
await _api._get('$_path/$id?' + _buildQuery({'market': market?.name}));
return EpisodeFull.fromJson(jsonDecode(jsonString));
}

Future<Iterable<EpisodeFull>> list(List<String> ids, [Market? market]) async {
assert(ids.isNotEmpty, 'No episode id\'s were provided');
var jsonString = await _api._get('$_path?' +
_buildQuery({
'ids': ids.join(','),
'market': market?.name,
}));
var episodesJson = jsonDecode(jsonString)['episodes'] as Iterable<dynamic>;
return episodesJson.map((json) => EpisodeFull.fromJson(json));
}
Future<Iterable<EpisodeFull>> list(List<String> ids,
[Market? market]) async =>
_listWithIds(
path: _path,
ids: ids,
jsonKey: 'episodes',
fromJson: EpisodeFull.fromJson,
optionalParams: {'market': market?.name});
}
9 changes: 2 additions & 7 deletions lib/src/endpoints/shows.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,8 @@ class Shows extends EndpointPaging {
}

/// Get one or several shows
Future<Iterable<Show>> list(List<String> showsId) async {
final jsonString = await _get('$_path?ids=${showsId.join(',')}');
final map = json.decode(jsonString);

final showsMap = map['shows'] as Iterable<dynamic>;
return showsMap.map((m) => Show.fromJson(m));
}
Future<Iterable<Show>> list(List<String> showsId) async => _listWithIds(
path: _path, ids: showsId, jsonKey: 'shows', fromJson: Show.fromJson);

/// Get a Show's Episodes
///
Expand Down
8 changes: 2 additions & 6 deletions lib/src/endpoints/tracks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,8 @@ class Tracks extends EndpointBase {
return Track.fromJson(map);
}

Future<Iterable<Track>> list(Iterable<String> trackIds) async {
final jsonString = await _api._get('$_path?ids=${trackIds.join(',')}');
final map = json.decode(jsonString);
final artistsMap = map['tracks'] as Iterable<dynamic>;
return artistsMap.map((m) => Track.fromJson(m));
}
Future<Iterable<Track>> list(List<String> trackIds) async => _listWithIds(
path: _path, ids: trackIds, jsonKey: 'tracks', fromJson: Track.fromJson);

/// queries track batches of size [queryLimit] from [trackIds] and yields Track object Iterables
Stream<Iterable<Track>> listInBatches(Iterable<String> trackIds,
Expand Down
42 changes: 42 additions & 0 deletions test/data/v1/artists/0TnOYISbd1XYRBk9myaseg/related-artists.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"artists": [
{
"external_urls": {
"spotify": "https://open.spotify.com/artist/0jnsk9HBra6NMjO2oANoPY"
},
"followers": {
"href": null,
"total": 8953912
},
"genres": [
"dance pop",
"miami hip hop",
"pop",
"pop rap"
],
"href": "https://api.spotify.com/v1/artists/0jnsk9HBra6NMjO2oANoPY",
"id": "0jnsk9HBra6NMjO2oANoPY",
"images": [
{
"height": 640,
"url": "https://i.scdn.co/image/ab6761610000e5eb655ca8f3196953554b479452",
"width": 640
},
{
"height": 320,
"url": "https://i.scdn.co/image/ab67616100005174655ca8f3196953554b479452",
"width": 320
},
{
"height": 160,
"url": "https://i.scdn.co/image/ab6761610000f178655ca8f3196953554b479452",
"width": 160
}
],
"name": "Flo Rida",
"popularity": 77,
"type": "artist",
"uri": "spotify:artist:0jnsk9HBra6NMjO2oANoPY"
}
]
}
10 changes: 10 additions & 0 deletions test/spotify_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,16 @@ Future main() async {
expect(artists.length, 2);
});

test('getRelatedArtists', () async {
var relatedArtists =
await spotify.artists.relatedArtists('0TnOYISbd1XYRBk9myaseg');
var first = relatedArtists.first;
expect(first.id, '0jnsk9HBra6NMjO2oANoPY');
expect(first.href,
'https://api.spotify.com/v1/artists/0jnsk9HBra6NMjO2oANoPY');
expect(first.name, 'Flo Rida');
});

test('getError', () async {
spotify.mockHttpErrors =
[MockHttpError(statusCode: 401, message: 'Bad Request')].iterator;
Expand Down

0 comments on commit a99c15b

Please sign in to comment.