VadVergasov_Programming/5/Lab_153503_Verhasau/Tests/SouvenirControllerTest.cs
using Domain.Entities;
using Domain.Models;
using Moq;
using Microsoft.Extensions.Primitives;
using Lab_153503_Verhasau.Services.CategoryService;
using Lab_153503_Verhasau.Services.SouvenirService;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;

namespace Tests;

class CategoryComparer : IEqualityComparer<Category>
{
    public bool Equals(Category? x, Category? y)
    {
        if (ReferenceEquals(x, y))
            return true;

        if (x is null || y is null)
            return false;

        return x.Id == y.Id && x.Name == y.Name && x.NormalizedName == y.NormalizedName;
    }

    public int GetHashCode(Category obj)
    {
        int hash = 17;
        hash = hash * 23 + obj.Id.GetHashCode();
        hash = hash * 23 + obj.Name.GetHashCode();
        hash = hash * 23 + obj.NormalizedName.GetHashCode();
        return hash;
    }
}

public class SouvenirControllerTest
{
    private static List<Category> GetSampleCategories()
    {
        return new List<Category>() {
                new Category { Id = 1, Name = "Магнит", NormalizedName = "magneet"},
                new Category { Id = 2, Name = "Открытка", NormalizedName = "otkritka"}
            };
    }

    private static List<Souvenir> GetSampleSouvenirs()
    {
        return new List<Souvenir>()
            {
                new Souvenir {
                    Id = 1,
                    Name = "Ван Гог - Звездная ночь",
                    Category = GetSampleCategories().Single(x=>x.Name == "Магнит"),
                    Description = "Магнит на холодильник с кассной картиной",
                    Image = "images/night.jpeg",
                    Price = 10M,
                },
                new Souvenir {
                    Id = 2,
                    Name = "Микелянджело - Давид",
                    Category = GetSampleCategories().Single(x => x.Name == "Открытка"),
                    Description = "Открытка с изображением статуи “Давид” работы Микеланджело. На открытке также может быть надпись “Поздравляем с праздником!” или “С наилучшими пожеланиями!”.",
                    Image = "images/david.jpeg",
                    Price = 5.15M,
                },
            };
    }

    [Fact]
    public void Index_ReturnsViewWithListOfSouvenirsModel_WhenNotAjaxQuery()
    {
        //Arrange
        Mock<ICategoryService> categories_moq = new();
        categories_moq.Setup(m => m.GetCategoryAsync()).ReturnsAsync(new ResponseData<List<Category>>()
        {
            Data = GetSampleCategories()
        });

        Mock<ISouvenirService> souvenir_moq = new();
        souvenir_moq.Setup(m => m.GetSouvenirListAsync(null, 0)).ReturnsAsync(new ResponseData<ListModel<Souvenir>>()
        {
            Success = true,
            ErrorMessage = null,
            Data = new ListModel<Souvenir>()
            {
                Items = GetSampleSouvenirs()
            }
        });

        var header = new Dictionary<string, StringValues>();
        var controllerContext = new ControllerContext();
        var moqHttpContext = new Mock<HttpContext>();
        moqHttpContext.Setup(c => c.Request.Headers).Returns(new HeaderDictionary(header));
        controllerContext.HttpContext = moqHttpContext.Object;

        //Act
        var controller = new Lab_153503_Verhasau.Controllers.Souvenir(souvenir_moq.Object, categories_moq.Object) { ControllerContext = controllerContext };
        var result = controller.Index(null).Result;
        //Assert
        Assert.NotNull(result);
        var viewResult = Assert.IsType<ViewResult>(result);
        Assert.IsType<List<Souvenir>>(viewResult.Model);
    }

    [Fact]
    public void Index_ReturnsPartialView_WhenAjaxQuery()
    {
        //Arrange
        Mock<ICategoryService> categories_moq = new();
        categories_moq.Setup(m => m.GetCategoryAsync()).ReturnsAsync(new ResponseData<List<Category>>()
        {
            Data = new List<Category>() {
                new Category { Id = 1, Name = "Магнит", NormalizedName = "magneet"},
                new Category { Id = 2, Name = "Открытка", NormalizedName = "otkritka"}
            }
        });

        Mock<ISouvenirService> souvenir_moq = new();
        souvenir_moq.Setup(m => m.GetSouvenirListAsync(null, 0)).ReturnsAsync(new ResponseData<ListModel<Souvenir>>()
        {
            Success = true,
            ErrorMessage = null,
            Data = new ListModel<Souvenir>()
            {
                Items = new List<Souvenir>()
                {
                    new Souvenir {
                        Id = 1,
                        Name = "Ван Гог - Звездная ночь",
                        Category = GetSampleCategories().Single(x=>x.Name == "Магнит"),
                        Description = "Магнит на холодильник с кассной картиной",
                        Image = "images/night.jpeg",
                        Price = 10M,
                    },
                }
            }
        });

        var header = new Dictionary<string, StringValues>()
        {
            ["X-Requested-With"] = "XMLHttpRequest"
        };
        var controllerContext = new ControllerContext();
        var moqHttpContext = new Mock<HttpContext>();
        moqHttpContext.Setup(c => c.Request.Headers).Returns(new HeaderDictionary(header));
        controllerContext.HttpContext = moqHttpContext.Object;

        //Act
        var controller = new Lab_153503_Verhasau.Controllers.Souvenir(souvenir_moq.Object, categories_moq.Object) { ControllerContext = controllerContext };
        var result = controller.Index(null).Result;
        //Assert
        Assert.NotNull(result);
        var viewResult = Assert.IsType<PartialViewResult>(result);
    }

    [Fact]
    public void Index_ReturnsError404_WhenUnsuccessfullyReceivedCategories()
    {
        //Arrange
        Mock<ICategoryService> categories_moq = new();
        categories_moq.Setup(m => m.GetCategoryAsync()).ReturnsAsync(new ResponseData<List<Category>>()
        {
            Success = false
        });

        Mock<ISouvenirService> souvenir_moq = new();
        souvenir_moq.Setup(m => m.GetSouvenirListAsync(null, 0)).ReturnsAsync(new ResponseData<ListModel<Souvenir>>()
        {
            Success = true
        });

        var header = new Dictionary<string, StringValues>();
        var controllerContext = new ControllerContext();
        var moqHttpContext = new Mock<HttpContext>();
        moqHttpContext.Setup(c => c.Request.Headers).Returns(new HeaderDictionary(header));
        controllerContext.HttpContext = moqHttpContext.Object;

        //Act
        var controller = new Lab_153503_Verhasau.Controllers.Souvenir(souvenir_moq.Object, categories_moq.Object) { ControllerContext = controllerContext };
        var result = controller.Index(null).Result;
        //Assert
        Assert.NotNull(result);
        var viewResult = Assert.IsType<NotFoundObjectResult>(result);
        Assert.Equal(StatusCodes.Status404NotFound, viewResult.StatusCode);
    }

    [Fact]
    public void Index_ReturnsError404_WhenUnsuccessfullyReceivedSouvenirs()
    {
        //Arrange
        Mock<ICategoryService> categories_moq = new();
        categories_moq.Setup(m => m.GetCategoryAsync()).ReturnsAsync(new ResponseData<List<Category>>()
        {
            Success = true
        });

        Mock<ISouvenirService> souvenir_moq = new();
        souvenir_moq.Setup(m => m.GetSouvenirListAsync(null, 0)).ReturnsAsync(new ResponseData<ListModel<Souvenir>>()
        {
            Success = false
        });

        var header = new Dictionary<string, StringValues>();
        var controllerContext = new ControllerContext();
        var moqHttpContext = new Mock<HttpContext>();
        moqHttpContext.Setup(c => c.Request.Headers).Returns(new HeaderDictionary(header));
        controllerContext.HttpContext = moqHttpContext.Object;

        //Act
        var controller = new Lab_153503_Verhasau.Controllers.Souvenir(souvenir_moq.Object, categories_moq.Object) { ControllerContext = controllerContext };
        var result = controller.Index(null).Result;
        //Assert
        Assert.NotNull(result);
        var viewResult = Assert.IsType<NotFoundObjectResult>(result);
        Assert.Equal(StatusCodes.Status404NotFound, viewResult.StatusCode);
    }

    [Fact]
    public void Index_ViewDataContainsCategories_WhenSuccessfullyReceivedData()
    {
        //Arrange
        Mock<ICategoryService> categories_moq = new();
        categories_moq.Setup(m => m.GetCategoryAsync()).ReturnsAsync(new ResponseData<List<Category>>()
        {
            Data = GetSampleCategories()
        });

        Mock<ISouvenirService> souvenir_moq = new();
        souvenir_moq.Setup(m => m.GetSouvenirListAsync(null, 0)).ReturnsAsync(new ResponseData<ListModel<Souvenir>>()
        {
            Success = true,
            ErrorMessage = null,
            Data = new ListModel<Souvenir>()
            {
                Items = GetSampleSouvenirs()
            }
        });

        var header = new Dictionary<string, StringValues>();
        var controllerContext = new ControllerContext();
        var moqHttpContext = new Mock<HttpContext>();
        moqHttpContext.Setup(c => c.Request.Headers).Returns(new HeaderDictionary(header));
        controllerContext.HttpContext = moqHttpContext.Object;


        //Act
        var controller = new Lab_153503_Verhasau.Controllers.Souvenir(souvenir_moq.Object, categories_moq.Object) { ControllerContext = controllerContext };
        var result = controller.Index(null).Result;
        //Assert
        Assert.NotNull(result);
        var viewResult = Assert.IsType<ViewResult>(result);
        Assert.True(viewResult.ViewData.ContainsKey("allCategories"));

        Assert.Equal(GetSampleCategories(), viewResult.ViewData["allCategories"] as IEnumerable<Category>, new CategoryComparer());
    }

    [Fact]
    public void Index_ViewDataContainsValidCurrentCategoryValue_WhenCategoryParameterIsNotNull()
    {
        //Arrange
        Mock<ICategoryService> categories_moq = new();
        categories_moq.Setup(m => m.GetCategoryAsync()).ReturnsAsync(new ResponseData<List<Category>>()
        {
            Data = GetSampleCategories()
        });

        Mock<ISouvenirService> souvenir_moq = new();
        souvenir_moq.Setup(m => m.GetSouvenirListAsync("magneet", 0)).ReturnsAsync(new ResponseData<ListModel<Souvenir>>()
        {
            Data = new ListModel<Souvenir>()
            {
                Items = GetSampleSouvenirs()
            }
        });

        var header = new Dictionary<string, StringValues>();
        var controllerContext = new ControllerContext();
        var moqHttpContext = new Mock<HttpContext>();
        moqHttpContext.Setup(c => c.Request.Headers).Returns(new HeaderDictionary(header));
        controllerContext.HttpContext = moqHttpContext.Object;

        //Act
        var controller = new Lab_153503_Verhasau.Controllers.Souvenir(souvenir_moq.Object, categories_moq.Object) { ControllerContext = controllerContext };
        var result = controller.Index("magneet", 0).Result;
        //Assert
        Assert.NotNull(result);
        var viewResult = Assert.IsType<ViewResult>(result);
        Assert.True(viewResult.ViewData.ContainsKey("currentCategory"));
        Assert.Equal("Магнит", viewResult.ViewData["currentCategory"] as string);
    }

    [Fact]
    public void Index_ViewDataContainsValidCurrentCategoryValue_WhenCategoryParameterIsNull()
    {
        //Arrange
        Mock<ICategoryService> categories_moq = new();
        categories_moq.Setup(m => m.GetCategoryAsync()).ReturnsAsync(new ResponseData<List<Category>>()
        {
            Data = GetSampleCategories()
        });

        Mock<ISouvenirService> souvenir_moq = new();
        souvenir_moq.Setup(m => m.GetSouvenirListAsync(null, 0)).ReturnsAsync(new ResponseData<ListModel<Souvenir>>()
        {
            Data = new ListModel<Souvenir>()
            {
                Items = GetSampleSouvenirs()
            }
        });

        var header = new Dictionary<string, StringValues>();
        var controllerContext = new ControllerContext();
        var moqHttpContext = new Mock<HttpContext>();
        moqHttpContext.Setup(c => c.Request.Headers).Returns(new HeaderDictionary(header));
        controllerContext.HttpContext = moqHttpContext.Object;

        //Act
        var controller = new Lab_153503_Verhasau.Controllers.Souvenir(souvenir_moq.Object, categories_moq.Object) { ControllerContext = controllerContext };
        var result = controller.Index(null).Result;
        //Assert
        Assert.NotNull(result);
        var viewResult = Assert.IsType<ViewResult>(result);
        Assert.True(viewResult.ViewData.ContainsKey("currentCategory"));
        Assert.Equal("Все", viewResult.ViewData["currentCategory"] as string);
    }
}