import os import unittest from sys import stderr from flask import Response, url_for from moto import mock_secretsmanager from structlog import getLogger from delphi_api.v2.data_models.amazon import ( AmazonPlaylistStream, AmazonPlaylistTrackStream, AmazonTrackStream, ) from delphi_api.v2.data_models.apple import AppleTrackStream from delphi_api.v2.data_models.spotify import SpotifyTrackStream from delphi_api.v2.data_models.youtube import YouTubeTrackStream from delphi_api.v2.proto.gen.amazon_v2_pb2 import AmazonTrackStreamStats from delphi_api.v2.proto.gen.apple_v2_pb2 import AppleTrackStreamStats from delphi_api.v2.proto.gen.spotify_v2_pb2 import SpotifyTrackStreamStats from delphi_api.v2.proto.gen.youtube_v2_pb2 import YouTubeTrackStreamStats from tests.mocks import patch_decode_token, patch_get_secret from tests.utils import UnitTestUtils from tests.v2.constants import AMAZON_ROUTES, APPLE_ROUTES, SPOTIFY_ROUTES, YOUTUBE_ROUTES LOG = getLogger(__name__) _SERVER_NAME = 'localhost:5000' # Models to create tables and fixture data for # format is { model class: proto class } _MODELS = { # Amazon AmazonTrackStream: AmazonTrackStreamStats, AmazonPlaylistTrackStream: AmazonTrackStreamStats, AmazonPlaylistStream: AmazonTrackStreamStats, # Apple AppleTrackStream: AppleTrackStreamStats, # Spotify SpotifyTrackStream: SpotifyTrackStreamStats, # YouTube YouTubeTrackStream: YouTubeTrackStreamStats, } # Note only routes that are registered within the app (via swagger) will be called # Any routes included here but not registered will simply be ignored _ROUTES = AMAZON_ROUTES + APPLE_ROUTES + SPOTIFY_ROUTES + YOUTUBE_ROUTES @mock_secretsmanager class TestEndpoints(unittest.TestCase): def setUp(self): self.mock_decode = patch_decode_token() self.mock_decode.start() self.patch_get_secret = patch_get_secret() self.patch_get_secret.start() from delphi_api.core.app import get_app self.app = get_app().app self.app.testing = True self.app.config['SERVER_NAME'] = _SERVER_NAME self.client = self.app.test_client() self.endpoints = UnitTestUtils.get_endpoints(self.app) emulator_host = os.getenv('BIGTABLE_EMULATOR_HOST') if not emulator_host or os.getenv('ENVIRONMENT') != 'test': raise EnvironmentError('BigTable emulator environment variable not set. ' 'Ensure the emulator is running and the env variable is set.') print('BIGTABLE_EMULATOR_HOST = %s' % emulator_host, file=stderr) # Create fixture tables for model_cls, parent_cls in _MODELS.items(): model = model_cls() model.create_table() has_isrc = hasattr(model, 'isrc') has_playlist_id = hasattr(model, 'playlist_id') # populate nested models parent = parent_cls() stream_stats = UnitTestUtils.populate_protobuf_models(parent) # Create some dummy data for each table if has_isrc and has_playlist_id: UnitTestUtils.create_playlist_track_streams(model, stream_stats) elif has_isrc and not has_playlist_id: UnitTestUtils.create_track_streams(model, stream_stats) elif not has_isrc and has_playlist_id: UnitTestUtils.create_playlists(model, stream_stats) def test_endpoints(self): with self.app.app_context(): headers = {'Authorization': 'Bearer 100'} for item in _ROUTES: route = item['route'] params = item['params'] endpoint = self.endpoints.get(route) if not endpoint: LOG.warning('Skipping testing for route: %s (Not Implemented)' % route) continue url = url_for(endpoint, **params) response: Response = self.client.get(url, headers=headers) data = response.json msg = f'route: {route}, params: {params}' self.assertTrue(len(data.get('items', [])), msg=f'No data in `items`, {msg}') self.assertEqual(response.status_code, 200, msg=f'Status code != 200, {msg}') def tearDown(self): for model in _MODELS: model().delete_table() self.mock_decode.stop() self.patch_get_secret.stop()