import base64 import json import os from dataclasses import dataclass from http import HTTPMethod import layercake.jsonl as jsonl import pytest from layercake.dynamodb import DynamoDBPersistenceLayer PYTEST_TABLE_NAME = 'pytest' PK = os.getenv('DYNAMODB_PARTITION_KEY', 'pk') SK = os.getenv('DYNAMODB_SORT_KEY', 'sk') @dataclass class LambdaContext: function_name: str = 'test' memory_limit_in_mb: int = 128 invoked_function_arn: str = 'arn:aws:lambda:eu-west-1:809313241:function:test' aws_request_id: str = '52fdfc07-2182-154f-163f-5f0f9a621d72' class HttpApiProxy: def __call__( self, raw_path: str, method: str = HTTPMethod.GET, body: dict = {}, *, headers: dict = {}, **kwargs, ) -> dict: return { 'version': '2.0', 'routeKey': '$default', 'rawPath': raw_path, 'rawQueryString': 'parameter1=value1¶meter1=value2¶meter2=value', 'cookies': ['cookie1', 'cookie2'], 'headers': headers, 'queryStringParameters': { 'parameter1': 'value1,value2', 'parameter2': 'value', }, 'requestContext': { 'accountId': '123456789012', 'apiId': 'api-id', 'authorizer': { 'lambda': { 'user': { 'name': 'Sérgio R Siqueira', 'email': 'sergio@somosbeta.com.br', 'email_verified': 'true', 'custom:user_id': '5OxmMjL-ujoR5IMGegQz', 'sub': 'c4f30dbd-083e-4b84-aa50-c31afe9b9c01', }, }, 'jwt': { 'claims': {'claim1': 'value1', 'claim2': 'value2'}, 'scopes': ['scope1', 'scope2'], }, }, 'domainName': 'id.execute-api.us-east-1.amazonaws.com', 'domainPrefix': 'id', 'http': { 'method': str(method), 'path': raw_path, 'protocol': 'HTTP/1.1', 'sourceIp': '192.168.0.1/32', 'userAgent': 'agent', }, 'requestId': 'id', 'routeKey': '$default', 'stage': '$default', 'time': '12/Mar/2020:19:03:58 +0000', 'timeEpoch': 1583348638390, }, 'body': _base64_dict(body), 'pathParameters': {'parameter1': 'value1'}, 'isBase64Encoded': True, 'stageVariables': {'stageVariable1': 'value1', 'stageVariable2': 'value2'}, } def _base64_dict(obj: dict = {}) -> str | None: if not obj: return None return base64.b64encode(json.dumps(obj).encode()).decode() @pytest.fixture def lambda_context() -> LambdaContext: return LambdaContext() @pytest.fixture def http_api_proxy(): return HttpApiProxy() @pytest.fixture def dynamodb_client(): from boto3clients import dynamodb_client as client client.create_table( AttributeDefinitions=[ {'AttributeName': PK, 'AttributeType': 'S'}, {'AttributeName': SK, 'AttributeType': 'S'}, ], TableName=PYTEST_TABLE_NAME, KeySchema=[ {'AttributeName': PK, 'KeyType': 'HASH'}, {'AttributeName': SK, 'KeyType': 'RANGE'}, ], ProvisionedThroughput={ 'ReadCapacityUnits': 123, 'WriteCapacityUnits': 123, }, ) yield client client.delete_table(TableName=PYTEST_TABLE_NAME) @pytest.fixture() def dynamodb_persistence_layer(dynamodb_client) -> DynamoDBPersistenceLayer: return DynamoDBPersistenceLayer(PYTEST_TABLE_NAME, dynamodb_client) @pytest.fixture() def dynamodb_seeds(dynamodb_client): with jsonl.readlines('tests/seeds.jsonl') as lines: for line in lines: dynamodb_client.put_item(TableName=PYTEST_TABLE_NAME, Item=line) @pytest.fixture def mock_app(monkeypatch): for table_name in ['USER_TABLE', 'COURSE_TABLE']: monkeypatch.setenv(table_name, PYTEST_TABLE_NAME) import app return app