public void given_a_request_when_ProcessImageUseCase_ExecuteGet_method_is_called_then_it_returns_the_response_object_of_correct_type_and_data()
        {
            //assert
            var request  = MatProcessDataHelper.CreateGetProcessImageRequestObject();
            var imageKey = ImagePersistingHelper.generateImageKey(request.processType, request.imageId, request.processRef, request.fileExtension);

            var expectedBase64ImageString = MatProcessDataHelper.CreatePostProcessImageRequestObject().base64Image;

            _mockGateway.Setup(g => g.RetrieveImage(It.Is <string>(obj => obj == imageKey))).Returns(expectedBase64ImageString);

            var expectedUsecaseResponse = new GetProcessImageResponse(expectedBase64ImageString, DateTime.Now, request); //The date time is impossible to test equality for, as it will differ in few microseconds from the actual response one. So I set it to DateTime.Min to signify its unimportance.

            //act
            var usecaseResponse = _processImageUseCase.ExecuteGet(request);

            //assert
            Assert.IsNotNull(usecaseResponse);
            Assert.IsInstanceOf <GetProcessImageResponse>(usecaseResponse);

            Assert.AreEqual(expectedUsecaseResponse.Base64Image, usecaseResponse.Base64Image);
            Assert.AreEqual(expectedUsecaseResponse.Request.processRef, usecaseResponse.Request.processRef);
            Assert.AreEqual(expectedUsecaseResponse.Request.imageId, usecaseResponse.Request.imageId);

            //This assertion has an accuracy of 1 second. If time difference between [when expected object was created] and [when actual usecase response was created] is within 1 second, then the times are considered equal. 1 Second is plenty of time for the code in between to run, considering it's using a Mock gateway.
            Assert.Less((usecaseResponse.GeneratedAt - expectedUsecaseResponse.GeneratedAt).TotalMilliseconds, 1000);
        }
        public void given_a_request_with_valid_base64Image_string_when_postProcessImageRequestValidator_is_called_then_it_returns_no_error()
        {
            //arange
            var request = MatProcessDataHelper.CreatePostProcessImageRequestObject();

            //act, assert
            _postValidator.ShouldNotHaveValidationErrorFor(req => req.base64Image, request);
        }
        [TestCase("ju5t70m3-w0rd-th4t-w1ll-m34nn0th1ng0")] //uses characters that are not among hexadecimal numerals
        public void given_a_request_with_invalid_ImageId_guid_when_postProcessImageRequestValidator_is_called_then_it_returns_an_error(string imageId)
        {
            //arrange
            var request = MatProcessDataHelper.CreatePostProcessImageRequestObject();

            request.imageId = imageId;

            //act, assert
            _postValidator.ShouldHaveValidationErrorFor(req => req.imageId, request).WithErrorMessage("You need to provide a valid Image Id.");
        }
        public void given_a_request_with_null_empty_or_whitespace_base64Image_string_when_postProcessImageRequestValidator_is_called_then_it_returns_an_error(string base64Image)
        {
            //arrange
            var request = MatProcessDataHelper.CreatePostProcessImageRequestObject();

            request.base64Image = base64Image;

            //act, assert
            _postValidator.ShouldHaveValidationErrorFor(req => req.base64Image, request).WithErrorMessage("Base64 Image string must be provided.");
        }
        public void given_a_request_with_null_empty_or_whitespace_processRef_when_postProcessImageRequestValidator_is_called_then_it_returns_an_error(string processRef)
        {
            //arrange
            var request = MatProcessDataHelper.CreatePostProcessImageRequestObject();

            request.processRef = processRef;

            //act, assert
            _postValidator.ShouldHaveValidationErrorFor(req => req.processRef, request).WithErrorMessage("Process reference must be provided.");
        }
        [TestCase("data:image/zz;base64,/1j/7TTQSkZJRgACAQEASBBI/2wBDAAgG\\BgcGBQgHwcJCQg")]     //file extension in the data bit is less than 3 chars long
        public void given_a_request_with_an_invalid_base64Image_string_when_postProcessImageRequestValidator_is_called_then_it_returns_an_error(string base64Image)
        {
            //arrange
            var request = MatProcessDataHelper.CreatePostProcessImageRequestObject();

            request.base64Image = base64Image;

            //act, assert
            _postValidator.ShouldHaveValidationErrorFor(req => req.base64Image, request).WithErrorMessage("You need to provide a valid Base64 Image string.");
        }
        public void given_a_request_when_ProcessImageUseCase_ExecutePost_method_is_called_then_it_calls_the_ProcessImageDecoder_with_imageString_from_request()
        {
            //arrange
            var request = MatProcessDataHelper.CreatePostProcessImageRequestObject();

            _mockImageDecoder.Setup(x => x.DecodeBase64ImageString(request.base64Image)).Returns(new Base64DecodedData()
            {
                imageExtension = _faker.Random.Word()
            });
            //act
            _processImageUseCase.ExecutePost(request);

            //assert
            _mockImageDecoder.Verify(d => d.DecodeBase64ImageString(It.Is <string>(s => s == request.base64Image)), Times.Once);
        }
        public void when_ProcessImageUseCase_ExecutePost_method_is_called_then_it_calls_the_gateway()
        {
            //arrange
            var request = MatProcessDataHelper.CreatePostProcessImageRequestObject();

            _mockImageDecoder.Setup(x => x.DecodeBase64ImageString(request.base64Image)).Returns(new Base64DecodedData()
            {
                imageExtension = _faker.Random.Word()
            });
            //act
            _processImageUseCase.ExecutePost(request);

            //assert
            _mockGateway.Verify(g => g.UploadImage(It.IsAny <ProcessImageData>()), Times.Once);
        }
        public void given_a_request_and_decodedBase64Data_objects_when_CreateImageDataObject_factory_method_is_called_then_it_outputs_correctly_populated_ProcessImageData_object()
        {
            //arrange
            var request     = MatProcessDataHelper.CreatePostProcessImageRequestObject();
            var decodedData = MatProcessDataHelper.CreateBase64DecodedDataObject();

            //act
            var processImageData = ImageDataFactory.CreateImageDataObject(request, decodedData);

            //asssert
            Assert.AreEqual(request.processRef, processImageData.processRef);
            Assert.AreEqual(request.imageId, processImageData.imageId);
            Assert.AreEqual(decodedData.imageType, processImageData.imageData.imageType);
            Assert.AreEqual(decodedData.imageExtension, processImageData.imageData.imageExtension);
            Assert.True(decodedData.imagebase64String.SequenceEqual(processImageData.imageData.imagebase64String));
        }
        public void given_valid_request_when_postProcessImage_controller_method_is_called_then_usecase_is_called_with_correct_data()
        {
            //arange
            var request = MatProcessDataHelper.CreatePostProcessImageRequestObject();

            _mockPostValidator.Setup(x => x.Validate(request)).Returns(new FV.ValidationResult()); //setup validator to return a no error validation result

            //act
            _processImageController.PostProcessImage(request);

            //assert
            _mockUsecase.Verify(u => u.ExecutePost(It.Is <PostProcessImageRequest>(obj =>
                                                                                   obj.processRef == request.processRef &&
                                                                                   obj.imageId == request.imageId &&
                                                                                   obj.base64Image == request.base64Image
                                                                                   )), Times.Once);
        }
        public void given_a_request_object_when_ProcessImageUseCase_ExecutePost_method_is_called_then_it_calls_the_gateway_with_correct_data() //test to see if usecase calls gateway with domain correctly built domain object
        {
            //arrange
            var request     = MatProcessDataHelper.CreatePostProcessImageRequestObject();
            var decodedData = MatProcessDataHelper.CreateBase64DecodedDataObject();

            _mockImageDecoder.Setup(d => d.DecodeBase64ImageString(It.IsAny <string>())).Returns(decodedData); //At this step, this test does not care about the validity of the decoder output, it only cares to see if the usecase passes the decoder output into gateway or not.

            //act
            _processImageUseCase.ExecutePost(request);

            //assert
            _mockGateway.Verify(g => g.UploadImage(It.Is <ProcessImageData>(obj =>
                                                                            obj.processRef == request.processRef &&
                                                                            obj.imageId == request.imageId &&
                                                                            obj.imageData.imagebase64String.SequenceEqual(decodedData.imagebase64String) &&
                                                                            obj.imageData.imageType == decodedData.imageType &&
                                                                            obj.imageData.imageExtension == decodedData.imageExtension &&
                                                                            obj.key == $"{request.processType}/{request.processRef}/{request.imageId}.{decodedData.imageExtension}"
                                                                            )), Times.Once);
        }