def test_on_package_created_products(order, listener, table_name,
                                     event_bus_name):
    """
    Test OnEvents function on a PackageCreated event when there are less products
    """

    eventbridge = boto3.client("events")
    table = boto3.resource("dynamodb").Table(table_name)  # pylint: disable=no-member

    # Store order in DynamoDB table
    table.put_item(Item=order)

    package_order = copy.deepcopy(order)
    removed_product = package_order["products"].pop(0)

    # Create the event
    event = {
        "Time": datetime.datetime.now(),
        "Source": "ecommerce.warehouse",
        "DetailType": "PackageCreated",
        "Resources": [order["orderId"]],
        "Detail": json.dumps(package_order),
        "EventBusName": event_bus_name
    }

    # Check events
    listener(
        "ecommerce.orders", lambda: eventbridge.put_events(Entries=[event]),
        lambda m: (order["orderId"] in m["resources"] and m[
            "detail-type"] == "OrderModified" and "status" in m["detail"][
                "changed"] and "products" in m["detail"]["changed"] and m[
                    "detail"]["new"]["status"] == "PACKAGED"))

    # Clean up
    table.delete_item(Key={"orderId": order["orderId"]})
def test_on_delivery_failed(order, listener, table_name, event_bus_name):
    """
    Test OnEvents function on a DeliveryFailed event
    """

    eventbridge = boto3.client("events")
    table = boto3.resource("dynamodb").Table(table_name)  # pylint: disable=no-member

    # Store order in DynamoDB table
    table.put_item(Item=order)

    # Create the event
    event = {
        "Time": datetime.datetime.now(),
        "Source": "ecommerce.delivery",
        "DetailType": "DeliveryFailed",
        "Resources": [order["orderId"]],
        "Detail": json.dumps(order),
        "EventBusName": event_bus_name
    }

    # Check events
    listener(
        "ecommerce.orders", lambda: eventbridge.put_events(Entries=[event]),
        lambda m: (order["orderId"] in m["resources"] and m["detail-type"] ==
                   "OrderModified" and "status" in m["detail"]["changed"] and
                   m["detail"]["new"]["status"] == "DELIVERY_FAILED"))

    # Clean up
    table.delete_item(Key={"orderId": order["orderId"]})
def test_table_update_failed(table_name, listener, order):
    """
    Test that the TableUpdate function reacts to changes to DynamoDB and sends events to EventBridge
    """

    table = boto3.resource("dynamodb").Table(table_name) # pylint: disable=no-member

    # Add a new item
    order["status"] = "NEW"
    table.put_item(Item=order)

    # Delete the item
    table.delete_item(Key={"orderId": order["orderId"]})

    # Listen for messages on EventBridge through a listener SQS queue
    messages = listener("delivery")

    # Parse messages
    found = False
    for message in messages:
        print("MESSAGE RECEIVED:", message)
        body = json.loads(message["Body"])
        if order["orderId"] in body["resources"]:
            found = True
            assert body["detail-type"] == "DeliveryFailed"

    assert found == True
Example #4
0
def test_table_update_failed(table_name, listener, order):
    """
    Test that the TableUpdate function reacts to changes to DynamoDB and sends events to EventBridge
    """

    table = boto3.resource("dynamodb").Table(table_name)  # pylint: disable=no-member

    # Add a new item
    order["status"] = "NEW"
    table.put_item(Item=order)

    # Listen for messages on EventBridge through a listener SQS queue
    listener(
        "ecommerce.delivery",
        lambda: table.delete_item(Key={"orderId": order["orderId"]}),
        lambda m: order["orderId"] in m["resources"] and m[
            "detail-type"] == "DeliveryFailed")
def test_on_package_created_products(order, listener, table_name,
                                     event_bus_name):
    """
    Test OnEvents function on a PackageCreated event when there are less products
    """

    eventbridge = boto3.client("events")
    table = boto3.resource("dynamodb").Table(table_name)  # pylint: disable=no-member

    # Store order in DynamoDB table
    table.put_item(Item=order)

    package_order = copy.deepcopy(order)
    removed_product = package_order["products"].pop(0)

    # Create the event
    event = {
        "Time": datetime.datetime.now(),
        "Source": "ecommerce.warehouse",
        "DetailType": "PackageCreated",
        "Resources": [order["orderId"]],
        "Detail": json.dumps(package_order),
        "EventBusName": event_bus_name
    }
    eventbridge.put_events(Entries=[event])

    # Wait
    time.sleep(5)

    # Check the DynamoDB table
    response = table.get_item(Key={"orderId": order["orderId"]})
    assert "Item" in response
    assert "status" in response["Item"]
    assert response["Item"]["status"] == "PACKAGED"
    assert len(response["Item"]["products"]) == len(package_order["products"])
    assert removed_product["productId"] not in [
        p["productId"] for p in response["Item"]["products"]
    ]

    # Check events
    messages = listener("orders", 5)
    found = False
    for message in messages:
        print("MESSAGE RECEIVED:", message)
        body = json.loads(message["Body"])
        if order["orderId"] in body["resources"] and body[
                "detail-type"] == "OrderModified":
            found = True
            assert "status" in body["detail"]["changed"]
            assert "products" in body["detail"]["changed"]
            assert body["detail"]["new"]["status"] == "PACKAGED"
    assert found == True

    # Clean up
    table.delete_item(Key={"orderId": order["orderId"]})
Example #6
0
def test_table_update(table_name, listener, product):
    """
    Test that the TableUpdate function reacts to changes to DynamoDB and sends
    events to EventBridge
    """
    # Add a new item
    table = boto3.resource("dynamodb").Table(table_name)  # pylint: disable=no-member

    # Listen for messages on EventBridge
    listener(
        "ecommerce.products", lambda: table.put_item(Item=product),
        lambda m: product["productId"] in m["resources"] and m[
            "detail-type"] == "ProductCreated")

    # Listen for messages on EventBridge
    listener(
        "ecommerce.products",
        lambda: table.delete_item(Key={"productId": product["productId"]}),
        lambda m: product["productId"] in m["resources"] and m[
            "detail-type"] == "ProductDeleted")
Example #7
0
def test_sign_up(listener):
    """
    Test that the SignUp function reacts to new users in Cognito User Pools and
    sends an event to EventBridge
    """

    data = {}

    def gen_func():
        email = "".join(random.choices(string.ascii_lowercase, k=20))+"@example.local"
        password = "".join(
            random.choices(string.ascii_uppercase, k=10) +
            random.choices(string.ascii_lowercase, k=10) +
            random.choices(string.digits, k=5) +
            random.choices(string.punctuation, k=3)
        )

        # Create a new user
        response = cognito.admin_create_user(
            UserPoolId=COGNITO_USER_POOL,
            Username=email,
            UserAttributes=[{
                "Name": "email",
                "Value": email
            }],
            # Do not send an email as this is a fake address
            MessageAction="SUPPRESS"
        )
        data["user_id"] = response["User"]["Username"]

    def test_func(m):
        return data["user_id"] in m["resources"] and m["detail-type"] == "UserCreated"

    # Listen for messages on EventBridge
    listener("ecommerce.users", gen_func, test_func)

    cognito.admin_delete_user(
        UserPoolId=COGNITO_USER_POOL,
        Username=data["user_id"]
    )
def test_table_update(table_name, listener, order):
    """
    Test that the TableUpdate function reacts to changes to DynamoDB and sends
    events to EventBridge
    """
    table = boto3.resource("dynamodb").Table(table_name)  # pylint: disable=no-member

    # Listen for messages on EventBridge
    listener(
        "ecommerce.orders",
        # Add a new item
        lambda: table.put_item(Item=order),
        lambda m: order["orderId"] in m["resources"] and m["detail-type"] ==
        "OrderCreated")

    # Listen for messages on EventBridge
    listener(
        "ecommerce.orders",
        # Change the status to cancelled
        lambda: table.update_item(Key={"orderId": order["orderId"]},
                                  UpdateExpression="set #s = :s",
                                  ExpressionAttributeNames={"#s": "status"},
                                  ExpressionAttributeValues=
                                  {":s": "CANCELLED"}),
        lambda m: order["orderId"] in m["resources"] and m["detail-type"] ==
        "OrderModified")

    # Listen for messages on EventBridge
    listener(
        "ecommerce.orders",
        # Delete the item
        lambda: table.delete_item(Key={"orderId": order["orderId"]}),
        lambda m: order["orderId"] in m["resources"] and m["detail-type"] ==
        "OrderDeleted")
Example #9
0
def test_table_update_completed(table_name, listener, order):
    """
    Test that the TableUpdate function reacts to changes to DynamoDB and sends events to EventBridge
    """

    table = boto3.resource("dynamodb").Table(table_name)  # pylint: disable=no-member

    # Add a new item
    order["status"] = "IN_PROGRESS"
    table.put_item(Item=order)

    # Set the item to COMPLETED
    order["status"] = "COMPLETED"

    # Listen for messages on EventBridge
    listener(
        "ecommerce.delivery", lambda: table.put_item(Item=order),
        lambda m: order["orderId"] in m["resources"] and m[
            "detail-type"] == "DeliveryCompleted")

    # Delete the item
    table.delete_item(Key={"orderId": order["orderId"]})
def test_listener(listener, event_bus_name):
    service_name = "ecommerce.test"
    resource = str(uuid.uuid4())
    event_type = "TestEvent"

    events = boto3.client("events")

    listener(service_name, lambda:
        events.put_events(Entries=[{
            "Time": datetime.datetime.utcnow(),
            "Source": service_name,
            "Resources": [resource],
            "DetailType": event_type,
            "Detail": "{}",
            "EventBusName": event_bus_name
        }]),
        lambda x: (
            x["source"] == service_name and
            x["resources"][0] == resource and
            x["detail-type"] == event_type
        )
    )
def test_table_update(table_name, listener, product):
    """
    Test that the TableUpdate function reacts to changes to DynamoDB and sends
    events to EventBridge
    """
    # Add a new item
    table = boto3.resource("dynamodb").Table(table_name) # pylint: disable=no-member
    table.put_item(Item=product)

    # Listen for messages on EventBridge through a listener SQS queue
    messages = listener("products")

    # Parse messages
    found = False
    for message in messages:
        print("MESSAGE RECEIVED:", message)
        body = json.loads(message["Body"])
        if product["productId"] in body["resources"]:
            found = True
            assert body["detail-type"] == "ProductCreated"

    assert found == True

    # Delete the item
    table.delete_item(Key={"productId": product["productId"]})

    # Listen for messages on EventBridge through a listener SQS queue
    messages = listener("products")

    # Parse messages
    found = False
    for message in messages:
        print("MESSAGE RECEIVED:", message)
        body = json.loads(message["Body"])
        if product["productId"] in body["resources"]:
            found = True
            assert body["detail-type"] == "ProductDeleted"

    assert found == True
Example #12
0
def test_table_update(table_name, metadata, products, listener):
    """
    Test that the TableUpdate function reacts to changes to DynamoDB and sends
    events to EventBridge
    """

    metadata = copy.deepcopy(metadata)

    # Create packaging request in DynamoDB
    table = boto3.resource("dynamodb").Table(table_name)  # pylint: disable=no-member

    with table.batch_writer() as batch:
        for product in products:
            batch.put_item(Item=product)
        batch.put_item(Item=metadata)

    # Mark the packaging as completed
    metadata["status"] = "COMPLETED"

    # Listen for messages on EventBridge
    listener(
        "ecommerce.warehouse", lambda: table.put_item(Item=metadata),
        lambda m: metadata["orderId"] in m["resources"] and m[
            "detail-type"] == "PackageCreated")

    # Clean up the table
    with table.batch_writer() as batch:
        table.delete_item(Key={
            "orderId": metadata["orderId"],
            "productId": metadata["productId"]
        })
        for product in products:
            table.delete_item(Key={
                "orderId": product["orderId"],
                "productId": product["productId"]
            })
def test_on_delivery_failed(order, listener, table_name, event_bus_name):
    """
    Test OnEvents function on a DeliveryFailed event
    """

    eventbridge = boto3.client("events")
    table = boto3.resource("dynamodb").Table(table_name)  # pylint: disable=no-member

    # Store order in DynamoDB table
    table.put_item(Item=order)

    # Create the event
    event = {
        "Time": datetime.datetime.now(),
        "Source": "ecommerce.delivery",
        "DetailType": "DeliveryFailed",
        "Resources": [order["orderId"]],
        "Detail": json.dumps(order),
        "EventBusName": event_bus_name
    }
    eventbridge.put_events(Entries=[event])

    # Wait
    time.sleep(5)

    # Check the DynamoDB table
    response = table.get_item(Key={"orderId": order["orderId"]})
    assert "Item" in response
    assert "status" in response["Item"]
    assert response["Item"]["status"] == "DELIVERY_FAILED"

    # Check events
    messages = listener("orders", 5)
    found = False
    for message in messages:
        print("MESSAGE RECEIVED:", message)
        body = json.loads(message["Body"])
        if order["orderId"] in body["resources"] and body[
                "detail-type"] == "OrderModified":
            found = True
            assert "status" in body["detail"]["changed"]
            assert body["detail"]["new"]["status"] == "DELIVERY_FAILED"
    assert found == True

    # Clean up
    table.delete_item(Key={"orderId": order["orderId"]})
def test_table_update(table_name, metadata, products, listener):
    """
    Test that the TableUpdate function reacts to changes to DynamoDB and sends
    events to EventBridge
    """

    metadata = copy.deepcopy(metadata)

    # Create packaging request in DynamoDB
    table = boto3.resource("dynamodb").Table(table_name) # pylint: disable=no-member

    with table.batch_writer() as batch:
        for product in products:
            batch.put_item(Item=product)
        batch.put_item(Item=metadata)

    # Mark the packaging as completed
    metadata["status"] = "COMPLETED"
    table.put_item(Item=metadata)

    # Listen for messages on EventBridge through a listener SQS queue
    messages = listener("warehouse", 15)

    # Parse messages
    found = False
    for message in messages:
        print("MESSAGE RECEIVED:", message)
        body = json.loads(message["Body"])
        if metadata["orderId"] in body["resources"]:
            found = True
            assert body["detail-type"] == "PackageCreated"

    assert found == True

    # Clean up the table
    with table.batch_writer() as batch:
        table.delete_item(Key={
            "orderId": metadata["orderId"],
            "productId": metadata["productId"]
        })
        for product in products:
            table.delete_item(Key={
                "orderId": product["orderId"],
                "productId": product["productId"]
            })
def test_sign_up(listener, user_id):
    """
    Test that the SignUp function reacts to new users in Cognito User Pools and
    sends an event to EventBridge
    """

    # Listen for messages on EventBridge through a listener SQS queue
    messages = listener("users")

    # Parse messages
    found = False
    for message in messages:
        print("MESSAGE RECEIVED:", message)
        body = json.loads(message["Body"])
        if user_id in body["resources"]:
            found = True
            assert body["detail-type"] == "UserCreated"

    assert found == True
Example #16
0
def test_table_update(table_name, listener, order):
    """
    Test that the TableUpdate function reacts to changes to DynamoDB and sends
    events to EventBridge
    """
    # Add a new item
    table = boto3.resource("dynamodb").Table(table_name)  # pylint: disable=no-member
    table.put_item(Item=order)

    # Listen for messages on EventBridge through a listener SQS queue
    messages = listener("orders")

    # Parse messages
    found = False
    for message in messages:
        print("MESSAGE RECEIVED:", message)
        body = json.loads(message["Body"])
        if order["orderId"] in body["resources"]:
            found = True
            assert body["detail-type"] == "OrderCreated"

    assert found == True

    # Change the status to cancelled
    table.update_item(Key={"orderId": order["orderId"]},
                      UpdateExpression="set #s = :s",
                      ExpressionAttributeNames={"#s": "status"},
                      ExpressionAttributeValues={":s": "CANCELLED"})

    # Listen for messages on EventBridge through a listener SQS queue
    messages = listener("orders")

    # Parse messages
    found = False
    for message in messages:
        print("MESSAGE RECEIVED:", message)
        body = json.loads(message["Body"])
        if order["orderId"] in body["resources"]:
            found = True
            assert body["detail-type"] == "OrderModified"
            detail = body["detail"]
            assert "changed" in detail
            assert "status" in detail["changed"]

    assert found == True

    # Delete the item
    table.delete_item(Key={"orderId": order["orderId"]})

    # Listen for messages on EventBridge through a listener SQS queue
    messages = listener("orders")

    # Parse messages
    found = False
    for message in messages:
        print("MESSAGE RECEIVED:", message)
        body = json.loads(message["Body"])
        if order["orderId"] in body["resources"]:
            found = True
            assert body["detail-type"] == "OrderDeleted"

    assert found == True