public async Task GetPhotosWithCommentsAndLikes_PassesExpectedQueryParametersAsync()
        {
            // Mock<IAmazonDynamoDB> dbClientMock = GetMockedDbClient();

            List <ScanRequest> observerdScanRequests = new List <ScanRequest>();

            dynamoDbCoreMock
            .Setup(x => x.Scan(It.IsAny <ScanRequest>(), It.IsAny <IValueMapper <Dictionary <string, AttributeValue> > >()))
            .Callback <ScanRequest, IValueMapper <Dictionary <string, AttributeValue> > >((query, valueMapper) => observerdScanRequests.Add(query))
            .Returns <ScanRequest, IValueMapper <Dictionary <string, AttributeValue> > >((query, valueMapper) => Task.FromResult(GetExpectedScanDataset()));

            //Given
            var repository = new DynamoDbPhotoRepository(dynamoDbCoreMock.Object, systemMock.Object, logWriterFactoryMock.Object);

            //When
            var items = await repository.GetPhotosWithCommentsAndLikesForScoring(referenceTime);

            //Then

            observerdScanRequests.Count.ShouldBe(2);
            observerdScanRequests[0].TableName.ShouldBe(tableName);
            observerdScanRequests[0].IndexName.ShouldBe("GSI2"); // from GetTouchedPhotoIds

            observerdScanRequests[1].IndexName.ShouldBeNull();
            observerdScanRequests[1].FilterExpression.ShouldNotBeEmpty();
        }
        public async Task GetPhotosWithCommentsAndLikes_ParsesResponseCorrectlyAsync()
        {
            var repository = new DynamoDbPhotoRepository(dynamoDbCoreMock.Object, systemMock.Object, logWriterFactoryMock.Object);

            var items = await repository.GetPhotosWithCommentsAndLikesForScoring(referenceTime);

            items.Count().ShouldBe(3);
            var firstItem = items.First();

            firstItem.Photo.ShouldNotBeNull();
            firstItem.Comments.Count().ShouldBe(4);
            firstItem.Likes.Count().ShouldBe(4);
        }
        public async Task SetPhotoText_NoHashtagChange_DoesNotCallBatchWriteItems()
        {
            Guid           photoId     = new Guid("36d8ba29-b39b-4e54-bdb4-c53ab5a89384");
            UserId         userId      = new Guid("c72e750d-c15f-43bf-be30-a94b5517f03e");
            DateTimeOffset createdTime = DateTimeOffset.UtcNow;

            var photo = new PhotoModel
            {
                PhotoId  = photoId,
                UserId   = userId,
                Hashtags = new[] {
                    new HashtagModel {
                        PhotoId = photoId, Hashtag = "#hashtag1"
                    },
                    new HashtagModel {
                        PhotoId = photoId, Hashtag = "#hashtag2"
                    }
                },
                State = PhotoState.PhotoAvailable
            };

            var repository = new DynamoDbPhotoRepository(dynamoDbCoreMock.Object, systemMock.Object, logWriterFactoryMock.Object);

            dynamoDbCoreMock
            .Setup(x => x.BatchGetItem(It.IsAny <BatchGetItemRequest>()))
            .Returns(() => GetBatchGetItemResponse(photo));

            bool batchWriteItemWasCalled = false;

            dynamoDbCoreMock
            .Setup(x => x.BatchWriteItem(It.IsAny <BatchWriteItemRequest>()))
            .Callback <BatchWriteItemRequest>(requests =>
            {
                batchWriteItemWasCalled = true;
            });

            HashtagModel[] newHashtags = new[]
            {
                new HashtagModel {
                    PhotoId = photo.PhotoId, Hashtag = "#hashtag1", CreatedTime = createdTime
                },
                new HashtagModel {
                    PhotoId = photo.PhotoId, Hashtag = "#hashtag2", CreatedTime = createdTime
                }
            };

            await repository.SetPhotoText(photo.UserId, photo.PhotoId, photo.RawText, newHashtags);

            batchWriteItemWasCalled.ShouldBeFalse();
        }
        public async Task SetPhotoText_AddAndRemovesHashtags()
        {
            Guid           photoId     = new Guid("36d8ba29-b39b-4e54-bdb4-c53ab5a89384");
            UserId         userId      = new Guid("c72e750d-c15f-43bf-be30-a94b5517f03e");
            DateTimeOffset createdTime = DateTimeOffset.UtcNow;

            var photo = new PhotoModel
            {
                PhotoId  = photoId,
                UserId   = userId,
                Hashtags = new[] {
                    new HashtagModel {
                        PhotoId = photoId, Hashtag = "#hashtag1"
                    },
                    new HashtagModel {
                        PhotoId = photoId, Hashtag = "#hashtag2"
                    }
                },
                State = PhotoState.PhotoAvailable
            };

            var repository = new DynamoDbPhotoRepository(dynamoDbCoreMock.Object, systemMock.Object, logWriterFactoryMock.Object);

            dynamoDbCoreMock
            .Setup(x => x.BatchGetItem(It.IsAny <BatchGetItemRequest>()))
            .Returns(() => GetBatchGetItemResponse(photo));

            BatchWriteItemRequest observedBatchRequest = null;

            dynamoDbCoreMock
            .Setup(x => x.BatchWriteItem(It.IsAny <BatchWriteItemRequest>()))
            .Callback <BatchWriteItemRequest>(requests =>
            {
                observedBatchRequest = requests;
            });

            HashtagModel[] newHashtags = new[]
            {
                new HashtagModel {
                    PhotoId = photo.PhotoId, Hashtag = "#hashtag1", CreatedTime = createdTime
                },
                new HashtagModel {
                    PhotoId = photo.PhotoId, Hashtag = "#hashtag3", CreatedTime = createdTime
                }
            };

            await repository.SetPhotoText(photo.UserId, photo.PhotoId, photo.RawText, newHashtags);

            observedBatchRequest.ShouldNotBeNull();
            var requestItems = observedBatchRequest.RequestItems[tableName];

            requestItems.Count.ShouldBe(2);
            var deleteRequest = requestItems.First(x => x.DeleteRequest != null);
            var putRequest    = requestItems.First(x => x.PutRequest != null);

            // verify that hashtag2 is removed
            deleteRequest.DeleteRequest.Key[FieldMappings.Hashtag.HastagId].S.ShouldBe("hash|hashtag2");
            deleteRequest.DeleteRequest.Key[FieldMappings.Hashtag.PhotoId].S.ShouldBe(photo.PhotoId.ToDbValue());

            // verify that hashtag3 is added
            putRequest.PutRequest.Item[FieldMappings.Hashtag.HastagId].S.ShouldBe("hash|hashtag3");
            putRequest.PutRequest.Item[FieldMappings.Hashtag.PhotoId].S.ShouldBe(photo.PhotoId.ToDbValue());
            putRequest.PutRequest.Item[FieldMappings.Hashtag.CreatedTime].S.ShouldBe(createdTime.ToString(Constants.DateTimeFormatWithMilliseconds));
        }