11import json
2- from datetime import datetime
3- from src .validation_lambda .app import valid_transaction , Status
42import base64
3+ import boto3
4+ import os
5+ from datetime import datetime
6+ from moto import mock_aws
7+ import pytest
8+ from src .validation_lambda .app import valid_transaction , Status , write_to_s3
9+
10+ # Setup environment variables for S3
11+ VALID_BUCKET = "valid-bucket"
12+ INVALID_BUCKET = "invalid-bucket"
13+ os .environ ["VALIDDATA_BUCKET_NAME" ] = VALID_BUCKET
14+ os .environ ["INVALIDDATA_BUCKET_NAME" ] = INVALID_BUCKET
15+
16+
17+ @pytest .fixture (scope = "function" )
18+ def s3_mock ():
19+ with mock_aws ():
20+ s3 = boto3 .client ("s3" )
21+ s3 .create_bucket (Bucket = VALID_BUCKET )
22+ s3 .create_bucket (Bucket = INVALID_BUCKET )
23+ yield s3
524
625
7- # Helper function to encode payloadds
826def encode_payload (payload ):
927 payload_json = json .dumps (payload )
10- return base64 .b64encode (payload_json .encode (' utf-8' )).decode (' utf-8' )
28+ return base64 .b64encode (payload_json .encode (" utf-8" )).decode (" utf-8" )
1129
1230
13- def decode_payload (payload ):
14- return payload
15-
1631# Sample valid transaction
1732def dummy_valid_transaction ():
1833 return {
@@ -22,100 +37,78 @@ def dummy_valid_transaction():
2237 "amount" : 254.67 ,
2338 "device_type" : "mobile" ,
2439 "location" : "California, USA" ,
25- "is_vpn" : "false" ,
40+ "is_vpn" : False ,
2641 "card_type" : "credit" ,
2742 "status" : "approved" ,
2843 }
2944
3045
31- # Test case for valid transaction
32- def test_valid_transaction_should_process ():
33- event = { "Records" : [{"kinesis" : {"data" : encode_payload (dummy_valid_transaction ())}}]}
34-
35- response = decode_payload ( valid_transaction (event , None ))[ ' data' ]
46+ def test_valid_transaction_should_process ( s3_mock ):
47+ event = {
48+ "Records" : [{"kinesis" : {"data" : encode_payload (dummy_valid_transaction ())}}]
49+ }
50+ response = valid_transaction (event , None )[ " data" ]
3651
3752 assert len (response ) == 1
3853 assert response [0 ]["status" ] == Status .ok .value
3954 assert response [0 ]["error" ] == ""
4055
56+ # Check if data is written to S3
57+ s3_objects = s3_mock .list_objects (Bucket = VALID_BUCKET )
58+ assert "Contents" in s3_objects
59+ assert len (s3_objects ["Contents" ]) == 1
4160
42- def test_transaction_with_json_data_in_kinesis_event ():
43- event = {"Records" : [{"kinesis" : {"data" : dummy_valid_transaction ()}}]}
61+ # should not write to invalid bucket
62+ s3_objects = s3_mock .list_objects (Bucket = INVALID_BUCKET )
63+ assert "Contents" not in s3_objects
4464
45- response = decode_payload (valid_transaction (event , None ))['data' ]
4665
47- assert len (response ) == 1
48- assert response [0 ]["status" ] == Status .ok .value
49- assert response [0 ]["error" ] == ""
50-
51-
52- # Test case for invalid transaction with missing fields
53- def test_invalid_transaction_missing_fields_should_return_empty_response ():
66+ def test_invalid_transaction_should_write_to_invalid_s3 (s3_mock ):
5467 invalid_payload = dummy_valid_transaction ()
5568 del invalid_payload ["transaction_id" ] # Remove a required field
5669 event = {"Records" : [{"kinesis" : {"data" : encode_payload (invalid_payload )}}]}
5770
58- response = decode_payload (valid_transaction (event , None ))['data' ]
59-
60- assert len (response ) == 0
71+ valid_transaction (event , None ) # Process transaction
6172
73+ # Check if invalid transaction is written to INVALID S3 bucket
74+ s3_objects = s3_mock .list_objects (Bucket = INVALID_BUCKET )
75+ assert "Contents" in s3_objects
76+ assert len (s3_objects ["Contents" ]) == 1
6277
63- # Test case for invalid transaction with incorrect format
64- def test_invalid_transaction_incorrect_format_should_return_empty_response ():
65- invalid_payload = dummy_valid_transaction ()
66- invalid_payload ["transaction_id" ] = "12345" # Does not match regex
67- event = {"Records" : [{"kinesis" : {"data" : encode_payload (invalid_payload )}}]}
78+ # should not write to valid bucket
79+ s3_objects = s3_mock .list_objects (Bucket = VALID_BUCKET )
80+ assert "Contents" not in s3_objects
6881
69- response = decode_payload (valid_transaction (event , None ))['data' ]
7082
71- assert len (response ) == 0
72-
73-
74- # Test case for multiple records
75- def test_multiple_transactions ():
83+ def test_multiple_transactions (s3_mock ):
7684 event = {
7785 "Records" : [
7886 {"kinesis" : {"data" : encode_payload (dummy_valid_transaction ())}},
7987 {"kinesis" : {"data" : encode_payload (dummy_valid_transaction ())}},
8088 ]
8189 }
82-
83- response = decode_payload (valid_transaction (event , None ))['data' ]
90+ response = valid_transaction (event , None )['data' ]
8491
8592 assert len (response ) == 2
8693 assert all (tx ["status" ] == Status .ok .value for tx in response )
8794
8895
89- def test_multiple_mix_transactions_should_filter_invalid_transactions ():
90- invalid_payload = dummy_valid_transaction ()
91- invalid_payload ["transaction_id" ] = "12345"
92- event = {
93- "Records" : [
94- {"kinesis" : {"data" : encode_payload (dummy_valid_transaction ())}},
95- {"kinesis" : {"data" : encode_payload (dummy_valid_transaction ())}},
96- {"kinesis" : {"data" : encode_payload (invalid_payload )}},
97- ]
98- }
99-
100- response = decode_payload (valid_transaction (event , None ))['data' ]
101-
102- assert len (response ) == 2
103-
104-
105- def test_output_is_json_serializable ():
96+ def test_output_is_json_serializable (s3_mock ):
10697 """Lambda expects output to be serializable"""
10798 event = {
10899 "Records" : [
109100 {"kinesis" : {"data" : encode_payload (dummy_valid_transaction ())}},
110101 ]
111102 }
112103
113- response = decode_payload ( valid_transaction (event , None ) )['data' ]
104+ response = valid_transaction (event , None )['data' ]
114105 assert json .dumps (response )
115106
116107
117- # Test case for empty event
118- def test_empty_event ():
119- event = {"Records" : []}
120- response = valid_transaction (event , None )
121- assert response == {'data' : []}
108+ def test_write_to_s3 (s3_mock ):
109+ content = json .dumps ({"test" : "data" })
110+ write_to_s3 (VALID_BUCKET , "test_transaction" , content )
111+
112+ s3_objects = s3_mock .list_objects (Bucket = VALID_BUCKET )
113+ assert "Contents" in s3_objects
114+ assert len (s3_objects ["Contents" ]) == 1
0 commit comments