def test_table_item(): # Create TableItem item = TableItem( file_name="somefile", file_path="path/to/somefile", file_url="www.example.com/content/path/to/somefile", status=None, release_date="Feb. 1, 2020", release_time="12:30AM", release="On Feb. 1, 2020 at 12:30AM", bad_datetime="bats", metadata={"some": {"thing": [4, 5, 6]}}, ) # Should have added all attributes to it's attribute list, # converted valid datetimes to UTC, ignored invalid datetimes, # and allowed NoneTypes assert item.attrs == { "file_name": "somefile", "file_path": "path/to/somefile", "file_url": "www.example.com/content/path/to/somefile", "status": None, "release_date": "2020-02-01T00:00:00", "release_time": "%sT00:30:00" % date.today(), "release": "2020-02-01T00:30:00", "bad_datetime": "bats", "metadata": '{"some": {"thing": [4, 5, 6]}}', } # Should have created class attributes for each kwarg for key, value in item.attrs.items(): assert getattr(item, key) == value
def test_upload_invalid_item(caplog): """Doesn't attempt to upload invalid items""" # Bunch of invalid items items = [ { "Item": "Invalid" }, "Not going to happen", TableItem(key1="test", key2=1234), [2, 4, 6, 8], ] client = MockedClient() with caplog.at_level(logging.DEBUG): client.upload(items=items, bucket_name="test_bucket") for msg in [ "Expected type 'BucketItem'", "dict", "str", "TableItem", "list", ]: assert msg in caplog.text client._session.resource().Bucket().upload_file.assert_not_called()
def test_search(): item = TableItem(key1=1234, attr1="hello") client = MockedClient() mocked_table = client._session.resource().Table() # Searching the table returns a dictionary with matching items mocked_table.query.return_value = { "Items": [{ "key1": 1234, "att1": "foo" }] } # Expected table attributes mocked_table.attribute_definitions = [ { "AttributeName": "key1", "AttributeType": "S" }, ] client.search(item, "test_table") mocked_table.query.assert_called_with( ExpressionAttributeValues={ ":key1val": "1234", ":attr1val": "hello" }, FilterExpression="attr1 = :attr1val", KeyConditionExpression="key1 = :key1val", Select="ALL_ATTRIBUTES", )
def test_publish_error(caplog): item = TableItem(key1="test", key2=1234) client = MockedClient() mocked_table = client._session.resource().Table() # Querying the table returns a dictionary of matching record items mocked_table.query.return_value = {"Items": []} # Expected table attributes mocked_table.attribute_definitions = [ { "AttributeName": "key1", "AttributeType": "S" }, { "AttributeName": "key2", "AttributeType": "S" }, ] # Some internal error when attempting to put the item mocked_table.put_item.side_effect = ValueError("Something went wrong") with caplog.at_level(logging.DEBUG): client.publish(item, "test_table") # Should've checked table for existing record... mocked_table.query.assert_called() for msg in [ "One or more exceptions occurred during publish", "Something went wrong", ]: assert msg in caplog.text
def test_publish_without_table_key(caplog): """Catches items missing keys required by the table""" item = TableItem(key1="test", key2=1234) client = MockedClient() mocked_table = client._session.resource().Table() # Querying the table returns a dictionary of matching record items mocked_table.query.return_value = {"Items": []} # Table contains unexpected keys mocked_table.attribute_definitions = [ { "AttributeName": "Nope", "AttributeType": "S" }, ] with caplog.at_level(logging.DEBUG): client.publish(item, "test_table") assert "Item to publish is missing required key, 'Nope'" in caplog.text # Should not have tried to publish mocked_table.put_item.assert_not_called()
def test_publish(dryrun, caplog): """Can publish TableItems""" items = [ TableItem(key1="test", key2=1234), TableItem(key1="testing", key2=5678), ] client = MockedClient() mocked_table = client._session.resource().Table() # Querying the table returns a dictionary with matching items mocked_table.query.return_value = {"Items": []} with caplog.at_level(logging.DEBUG): client.publish(items, "test_table", dryrun=dryrun) if dryrun: # Should've only logged what would've been done assert "Would publish" in caplog.text mocked_table.put_item.assert_not_called() else: # Should've checked table for existing record... assert mocked_table.query.call_count == 2 # ...and proceeded with publish assert "Table already up to date" not in caplog.text mocked_table.put_item.assert_has_calls( [ mock.call(Item={ "key1": "test", "key2": 1234 }), mock.call(Item={ "key1": "testing", "key2": 5678 }), ], any_order=True, ) assert "Publish complete" in caplog.text
def test_publish_duplicate(caplog): """Doesn't attempt to duplicate table items""" item = TableItem(key1="test", key2=1234) client = MockedClient() mocked_table = client._session.resource().Table() # Querying the table returns a dictionary of matching record items mocked_table.query.return_value = { "Items": [{ "key1": "test", "key2": 1234 }] } # Expected table attributes mocked_table.attribute_definitions = [ { "AttributeName": "key1", "AttributeType": "S" }, { "AttributeName": "key2", "AttributeType": "S" }, ] with caplog.at_level(logging.DEBUG): client.publish(item, "test_table") # Should've checked table for existing record... mocked_table.query.assert_called() # ...and found one assert "Item already exists in table" in caplog.text # Should not have tried to publish mocked_table.put_item.assert_not_called()
def test_search_response_too_large(caplog): item = TableItem(key1=1234, attr1="hello") client = MockedClient() mocked_table = client._session.resource().Table() # Searching the table returns a dictionary with matching items mocked_table.query.return_value = { "Items": ["Lots of items..."], "LastEvaluatedKey": { "key1": "test" }, } # Expected table attributes mocked_table.attribute_definitions = [ { "AttributeName": "key1", "AttributeType": "S" }, ] with caplog.at_level(logging.DEBUG): client.search(item, "test_table") mocked_table.query.assert_called_with( ExpressionAttributeValues={ ":key1val": "1234", ":attr1val": "hello" }, FilterExpression="attr1 = :attr1val", KeyConditionExpression="key1 = :key1val", Select="ALL_ATTRIBUTES", ) assert "Query limit reached, results truncated" in caplog.text