"""Tests for the dynamo connector.""" from unittest.mock import patch import pytest from boto3.dynamodb.conditions import Attr, Key from sound_recordings.connectors import dynamo QUERY_RESPONSE = {"Count": 1, "Items": [{"id": 1}]} GET_ITEM_RESPONSE = {"Item": {"id": 1}} range_key = "rng_key" hash_key = "hash_key" @pytest.fixture() def mock_query(): """Mock get_table().query.""" with patch("sound_recordings.connectors.dynamo._get_table") as get_table: get_table.return_value.query.return_value = QUERY_RESPONSE yield get_table().query @pytest.fixture() def mock_get_item(): """Mock get_table().get_item.""" with patch("sound_recordings.connectors.dynamo._get_table") as get_table: get_table.return_value.get_item.return_value = GET_ITEM_RESPONSE yield get_table().get_item def test_query_by_range_key(mock_query): """Test dynamo.query_by_range_key.""" response = dynamo.query_by_range_key(range_key) mock_query.assert_called_with( IndexName=dynamo.INDEX_NAME, KeyConditionExpression=Key(dynamo.RANGE_KEY).eq(range_key), ) assert QUERY_RESPONSE["Items"] == response def test_query_by_range_key_empty(mock_query): """Test dynamo.query_by_range_key.""" mock_query.return_value = {} response = dynamo.query_by_range_key(range_key) assert response == [] def test_query_by_range_keys(mock_query): """Test dynamo.query_by_keys for a list of range keys.""" range_keys = ["key1", "key2", "key3"] response = dynamo.query_by_keys(range_keys, key_type="range") for range_key in range_keys: mock_query.assert_any_call( IndexName=dynamo.INDEX_NAME, KeyConditionExpression=Key(dynamo.RANGE_KEY).eq(range_key), ) assert QUERY_RESPONSE["Items"] == list(response[0].values())[0] assert QUERY_RESPONSE["Items"] == list(response[1].values())[0] assert QUERY_RESPONSE["Items"] == list(response[2].values())[0] def test_query_by_range_keys_empty(mock_query): """Test dynamo.query_by_keys if no keys provided.""" range_keys = [] response = dynamo.query_by_keys(range_keys, key_type="range") assert response is None def test_query_by_hash_keys(mock_query): """Test dynamo.query_by_keys for a list of hash keys.""" hash_keys = ["key1", "key2", "key3"] response = dynamo.query_by_keys(hash_keys, key_type="hash") for hash_key in hash_keys: mock_query.assert_any_call( KeyConditionExpression=Key(dynamo.HASH_KEY).eq(hash_key) ) assert QUERY_RESPONSE["Items"] == list(response[0].values())[0] assert QUERY_RESPONSE["Items"] == list(response[1].values())[0] assert QUERY_RESPONSE["Items"] == list(response[2].values())[0] def test_query_by_hash_keys_empty(mock_query): """Test dynamo.query_by_keys if no hash keys provided.""" range_keys = [] response = dynamo.query_by_keys(range_keys, key_type="hash") assert response is None def test_query_by_hash_key(mock_query): """Test dynamo.query_by_hash_key.""" response = dynamo.query_by_hash_key(hash_key) mock_query.assert_called_with( KeyConditionExpression=Key(dynamo.HASH_KEY).eq(hash_key) ) assert QUERY_RESPONSE["Items"] == response def test_query_by_hash_key_empty(mock_query): """Test dynamo.query_by_hash_key with empty result.""" mock_query.return_value = {} response = dynamo.query_by_hash_key(hash_key) assert response == [] def test_create_track_key(): """Test dynamo.create_track_key.""" isrc = "NOOB" key = dynamo.create_track_key(isrc) assert key == "isrc:{}".format(isrc) @pytest.fixture def mock_query_by_hash_key(): """Mock top sound recordings.""" with patch( "sound_recordings.connectors.dynamo._query_by_hash_key" ) as mock_query_by_hash_key: mock_query_by_hash_key.return_value = None yield mock_query_by_hash_key @pytest.fixture def mock_query_by_range_key(): """Mock query_by_range_key.""" with patch( "sound_recordings.connectors.dynamo._query_by_range_key" ) as mock_query_by_range_key: mock_query_by_range_key.return_value = None yield mock_query_by_range_key @pytest.fixture def mock_get_table(): """Mock top sound recordings.""" with patch("sound_recordings.connectors.dynamo._get_table") as mock_get_table: mock_get_table.return_value = "Table" yield mock_get_table class TestLabel: """Dynamo Tests for labels.""" permissions_filter = { "label_ids": [123], "subaccount_ids": None, "artist_ids": None, } def test_product_permissions(self, mock_query_by_hash_key, mock_get_table): """Test dynamo.test_product_permissions.""" dynamo.query_by_hash_key("product:123") mock_query_by_hash_key.called_once_with( "product:123", "Table", Attr("label_id").is_in(self.permissions_filter["label_ids"]), ) def test_sound_recording_permissions(self, mock_query_by_range_key, mock_get_table): """Test dynamo.test_sound_recording_permissions.""" dynamo.query_by_range_key("isrc:123") mock_query_by_range_key.called_once_with( "isrc:123", "Table", Attr("label_id").is_in(self.permissions_filter["label_ids"]), ) class TestSubaccount: """Dynamo Tests for Subaccounts.""" permissions_filter = { "label_ids": [123], "subaccount_ids": [345], "artist_ids": None, } def test_parse_key(self): """Test dynamo.parse_key.""" label = 123 product = 345 subaccount = 915 unmapped = "is also extracted" key = "label:{}:product:{}:subaccount:{}:unmapped:{}".format( label, product, subaccount, unmapped ) assert dynamo.parse_key(key) == { "label_id": str(label), "product_id": str(product), "subaccount_id": str(subaccount), "unmapped": unmapped, } def test_product_permissions(self, mock_query_by_hash_key, mock_get_table): """Test dynamo.test_product_permissions.""" dynamo.query_by_hash_key("product:123") mock_query_by_hash_key.called_once_with( "product:123", "Table", Attr("product.subaccount_id").is_in( self.permissions_filter["subaccount_ids"] ), ) def test_sound_recording_permissions(self, mock_query_by_range_key, mock_get_table): """Test dynamo.test_sound_recording_permissions.""" dynamo.query_by_range_key("isrc:123") mock_query_by_range_key.called_once_with( "isrc:123", "Table", Attr("product.subaccount_id").is_in( self.permissions_filter["subaccount_ids"] ), ) class TestArtist: """Dynamo Tests for artists.""" permissions_filter = { "label_id": None, "subaccount_ids": None, "artist_ids": [123, 345], } def test_create_track_key(self): """Test dynamo.create_track_key with subaccount.""" isrc = "NOOB" key = dynamo.create_track_key(isrc) assert len(key.split(":")) == 2 assert dynamo.parse_key(key) == {"isrc": isrc} def test_create_product_key(self): """Test dynamo.create_product_key.""" product_id = 345 key = dynamo.create_product_key(product_id) assert len(key.split(":")) == 2 assert dynamo.parse_key(key) == {"product_id": str(product_id)} def test_product_permissions(self, mock_query_by_hash_key, mock_get_table): """Test dynamo.test_product_permissions.""" dynamo.query_by_hash_key("product:123") mock_query_by_hash_key.called_once_with( "product:123", "Table", Attr("artist_id").is_in(self.permissions_filter["artist_ids"]), ) def test_sound_recording_permissions(self, mock_query_by_range_key, mock_get_table): """Test dynamo.test_sound_recording_permissions.""" dynamo.query_by_range_key("isrc:123") mock_query_by_range_key.called_once_with( "isrc:123", "Table", Attr("product.subaccount_id").is_in( self.permissions_filter["subaccount_ids"] ), )