import json import pytest from common.src.aws import utils from common.src.enums import AWSPayload from unittest.mock import Mock S3_PREFIX = utils.AWSPrefixes.S3 SAMPLE_S3_BUCKET_NAME = "test-bucket" SAMPLE_S3_KEY_NAME = "test-blob/abc.txt" SAMPLE_S3_URI = f"{S3_PREFIX}{SAMPLE_S3_BUCKET_NAME}/{SAMPLE_S3_KEY_NAME}" class TestJsonOrSnsPayload: def test_json(self): json_payload = {"key": "value"} result = utils.json_or_sns_payload(json_payload) assert result == json_payload, "Expected the JSON payload to be returned as is" def test_json_with_records_key_lower_initial(self): json_payload = { # This is not a valid SNS payload (records key is lowercase) "records": [{"one": "value"}, {"two": "value"}, {"three": "value"}] } result = utils.json_or_sns_payload(json_payload) assert result == json_payload, "Expected the JSON payload to be returned as is" @staticmethod def new_sns_message(message_content): return { AWSPayload.RECORDS: [ {AWSPayload.SNS: {AWSPayload.MESSAGE: json.dumps(message_content)}} ] } def test_json_with_records_key_is_sns(self): sample_message = {"key": "value"} payload = self.new_sns_message(sample_message) result = utils.json_or_sns_payload(payload) assert ( result == sample_message ), "Expected the SNS message to be parsed correctly" def test_json_with_records_key_is_sns_no_messages(self): payload = {AWSPayload.RECORDS: []} result = utils.json_or_sns_payload(payload) assert ( result is None ), "Expected the result to be None when there are no records in the SNS payload" class TestGetS3BucketKeyFromUri: def test_valid(self): result = utils.get_s3_bucket_key_from_uri(SAMPLE_S3_URI) assert result == (SAMPLE_S3_BUCKET_NAME, SAMPLE_S3_KEY_NAME) def test_get_no_prefix(self): prefix_len = len(S3_PREFIX) s3_uri_no_prefix = SAMPLE_S3_URI[prefix_len:] with pytest.raises(ValueError): utils.get_s3_bucket_key_from_uri(s3_uri_no_prefix) def test_get_s3_empty_string(self): with pytest.raises(ValueError): utils.get_s3_bucket_key_from_uri("") class TestGetS3UriFromBucketKey: def test_valid(self): result = utils.get_s3_uri_from_bucket_key( SAMPLE_S3_BUCKET_NAME, SAMPLE_S3_KEY_NAME ) assert result == SAMPLE_S3_URI def test_empty_bucket_name(self): with pytest.raises(ValueError): utils.get_s3_uri_from_bucket_key("", SAMPLE_S3_KEY_NAME) def test_empty_key_name(self): with pytest.raises(ValueError): utils.get_s3_uri_from_bucket_key(SAMPLE_S3_BUCKET_NAME, "") class TestIterS3BucketContents: @pytest.mark.parametrize( "pages, expected_keys", [ ( [ { "Contents": [ {AWSPayload.KEY: "file1"}, {AWSPayload.KEY: "file2"}, ] }, {"Contents": [{AWSPayload.KEY: "file3"}]}, ], ["file1", "file2", "file3"], ), ( [{"Contents": []}, {}], [], ), ], ) def test_iter_s3_bucket_contents(self, pages, expected_keys): mock_paginator = Mock() mock_paginator.paginate.return_value = pages mock_client = Mock() mock_client.get_paginator.return_value = mock_paginator result = list(utils.iter_s3_bucket_contents(mock_client, "my-bucket")) assert [item[AWSPayload.KEY] for item in result] == expected_keys class TestGetSNSTopicARN: def setup_method(self): self.mock_client = Mock(autospec=True) def test_topic_arn_found(self): self.mock_client.list_topics.return_value = { AWSPayload.TOPICS: [ {AWSPayload.TOPIC_ARN: "arn:aws:sns:us-east-1:123:my-topic"}, {AWSPayload.TOPIC_ARN: "arn:aws:sns:us-east-1:123:other-topic"}, ] } result = utils.get_sns_topic_arn(self.mock_client, "my-topic") assert result == "arn:aws:sns:us-east-1:123:my-topic" def test_topic_arn_not_found(self): self.mock_client.list_topics.return_value = { AWSPayload.TOPICS: [ {AWSPayload.TOPIC_ARN: "arn:aws:sns:us-east-1:123:some-topic"}, ] } with pytest.raises( ValueError, match="No ARN found for topic name: missing-topic" ): utils.get_sns_topic_arn(self.mock_client, "missing-topic")