|
| 1 | +using Grand.Business.Core.Interfaces.Catalog.Brands; |
| 2 | +using Grand.Business.Core.Interfaces.Catalog.Categories; |
| 3 | +using Grand.Business.Core.Interfaces.Catalog.Collections; |
| 4 | +using Grand.Domain; |
| 5 | +using Grand.Domain.Admin; |
| 6 | +using Grand.Domain.Catalog; |
| 7 | +using Grand.Web.AdminShared.Controllers; |
| 8 | +using Grand.Web.Common.DataSource; |
| 9 | +using Microsoft.AspNetCore.Mvc; |
| 10 | +using Microsoft.VisualStudio.TestTools.UnitTesting; |
| 11 | +using Moq; |
| 12 | + |
| 13 | +namespace Grand.Web.Admin.Tests.Controllers; |
| 14 | + |
| 15 | +[TestClass] |
| 16 | +public class BaseSearchControllerTests |
| 17 | +{ |
| 18 | + // Concrete subclass exists only to instantiate the abstract base for direct-call unit tests, |
| 19 | + // with PickerStoreId parameterized so both the Admin/Vendor shape ("") and the Store shape (a |
| 20 | + // real store id) can be exercised without needing the 3 real host subclasses - same pattern as |
| 21 | + // BaseTaxCategoryControllerTests. |
| 22 | + private class TestSearchController( |
| 23 | + ICategoryService categoryService, |
| 24 | + IBrandService brandService, |
| 25 | + ICollectionService collectionService, |
| 26 | + AdminSearchSettings adminSearchSettings, |
| 27 | + string pickerStoreId) |
| 28 | + : BaseSearchController(categoryService, brandService, collectionService, adminSearchSettings) |
| 29 | + { |
| 30 | + protected override string PickerStoreId => pickerStoreId; |
| 31 | + } |
| 32 | + |
| 33 | + private Mock<ICategoryService> _categoryServiceMock = null!; |
| 34 | + private Mock<IBrandService> _brandServiceMock = null!; |
| 35 | + private Mock<ICollectionService> _collectionServiceMock = null!; |
| 36 | + private AdminSearchSettings _settings = null!; |
| 37 | + |
| 38 | + [TestInitialize] |
| 39 | + public void Setup() |
| 40 | + { |
| 41 | + _categoryServiceMock = new Mock<ICategoryService>(); |
| 42 | + _brandServiceMock = new Mock<IBrandService>(); |
| 43 | + _collectionServiceMock = new Mock<ICollectionService>(); |
| 44 | + _settings = new AdminSearchSettings { |
| 45 | + CategorySizeLimit = 10, |
| 46 | + CollectionSizeLimit = 10, |
| 47 | + BrandSizeLimit = 10 |
| 48 | + }; |
| 49 | + } |
| 50 | + |
| 51 | + private TestSearchController CreateController(string pickerStoreId) => |
| 52 | + new(_categoryServiceMock.Object, _brandServiceMock.Object, _collectionServiceMock.Object, _settings, pickerStoreId); |
| 53 | + |
| 54 | + private static DataSourceRequestFilter EmptyFilter() => new() { Filters = [] }; |
| 55 | + |
| 56 | + // Anonymous JSON payloads aren't used here (DataSourceResult is a public type with public |
| 57 | + // members), but Data's items are instances of a private nested record - read them via |
| 58 | + // reflection, same pattern established in BasePictureControllerTests. |
| 59 | + private static (string Id, string Name)[] ReadRows(IActionResult result) |
| 60 | + { |
| 61 | + var data = (System.Collections.IEnumerable)((JsonResult)result).Value!.GetType().GetProperty("Data")! |
| 62 | + .GetValue(((JsonResult)result).Value)!; |
| 63 | + var rows = new List<(string, string)>(); |
| 64 | + foreach (var item in data) |
| 65 | + { |
| 66 | + var id = (string)item.GetType().GetProperty("Id")!.GetValue(item)!; |
| 67 | + var name = (string)item.GetType().GetProperty("Name")!.GetValue(item)!; |
| 68 | + rows.Add((id, name)); |
| 69 | + } |
| 70 | + return rows.ToArray(); |
| 71 | + } |
| 72 | + |
| 73 | + [TestMethod] |
| 74 | + public async Task Category_DefaultPickerStoreId_PassesEmptyStoreIdToService() |
| 75 | + { |
| 76 | + var controller = CreateController(""); |
| 77 | + _categoryServiceMock |
| 78 | + .Setup(s => s.GetAllCategories(null, null, "", 0, 10, false)) |
| 79 | + .ReturnsAsync(new PagedList<Category>([new Category { Id = "cat-1", Name = "Books" }], 0, 10)); |
| 80 | + _categoryServiceMock.Setup(s => s.GetFormattedBreadCrumb(It.IsAny<Category>(), ">>", "")) |
| 81 | + .ReturnsAsync("Books"); |
| 82 | + |
| 83 | + var result = await controller.Category(null, EmptyFilter()); |
| 84 | + |
| 85 | + var rows = ReadRows(result); |
| 86 | + Assert.AreEqual(1, rows.Length); |
| 87 | + Assert.AreEqual("cat-1", rows[0].Id); |
| 88 | + _categoryServiceMock.Verify(s => s.GetAllCategories(null, null, "", 0, 10, false), Times.Once); |
| 89 | + } |
| 90 | + |
| 91 | + [TestMethod] |
| 92 | + public async Task Category_OverriddenPickerStoreId_PassesStoreIdToService() |
| 93 | + { |
| 94 | + var controller = CreateController("store-1"); |
| 95 | + _categoryServiceMock |
| 96 | + .Setup(s => s.GetAllCategories(null, null, "store-1", 0, 10, false)) |
| 97 | + .ReturnsAsync(new PagedList<Category>([], 0, 10)); |
| 98 | + |
| 99 | + await controller.Category(null, EmptyFilter()); |
| 100 | + |
| 101 | + _categoryServiceMock.Verify(s => s.GetAllCategories(null, null, "store-1", 0, 10, false), Times.Once); |
| 102 | + } |
| 103 | + |
| 104 | + [TestMethod] |
| 105 | + public async Task Collection_DefaultPickerStoreId_PassesEmptyStoreIdToService() |
| 106 | + { |
| 107 | + var controller = CreateController(""); |
| 108 | + _collectionServiceMock |
| 109 | + .Setup(s => s.GetAllCollections(null, "", 0, 10, false)) |
| 110 | + .ReturnsAsync(new PagedList<Collection>([new Collection { Id = "col-1", Name = "Summer" }], 0, 10)); |
| 111 | + |
| 112 | + var result = await controller.Collection(null, EmptyFilter()); |
| 113 | + |
| 114 | + var rows = ReadRows(result); |
| 115 | + Assert.AreEqual(1, rows.Length); |
| 116 | + Assert.AreEqual("Summer", rows[0].Name); |
| 117 | + _collectionServiceMock.Verify(s => s.GetAllCollections(null, "", 0, 10, false), Times.Once); |
| 118 | + } |
| 119 | + |
| 120 | + [TestMethod] |
| 121 | + public async Task Collection_OverriddenPickerStoreId_PassesStoreIdToService() |
| 122 | + { |
| 123 | + var controller = CreateController("store-1"); |
| 124 | + _collectionServiceMock |
| 125 | + .Setup(s => s.GetAllCollections(null, "store-1", 0, 10, false)) |
| 126 | + .ReturnsAsync(new PagedList<Collection>([], 0, 10)); |
| 127 | + |
| 128 | + await controller.Collection(null, EmptyFilter()); |
| 129 | + |
| 130 | + _collectionServiceMock.Verify(s => s.GetAllCollections(null, "store-1", 0, 10, false), Times.Once); |
| 131 | + } |
| 132 | + |
| 133 | + [TestMethod] |
| 134 | + public async Task Brand_DefaultPickerStoreId_PassesEmptyStoreIdToService() |
| 135 | + { |
| 136 | + var controller = CreateController(""); |
| 137 | + _brandServiceMock |
| 138 | + .Setup(s => s.GetAllBrands(null, "", 0, 10, false)) |
| 139 | + .ReturnsAsync(new PagedList<Brand>([new Brand { Id = "brand-1", Name = "Acme" }], 0, 10)); |
| 140 | + |
| 141 | + var result = await controller.Brand(null, EmptyFilter()); |
| 142 | + |
| 143 | + var rows = ReadRows(result); |
| 144 | + Assert.AreEqual(1, rows.Length); |
| 145 | + Assert.AreEqual("Acme", rows[0].Name); |
| 146 | + _brandServiceMock.Verify(s => s.GetAllBrands(null, "", 0, 10, false), Times.Once); |
| 147 | + } |
| 148 | + |
| 149 | + [TestMethod] |
| 150 | + public async Task Brand_OverriddenPickerStoreId_PassesStoreIdToService() |
| 151 | + { |
| 152 | + var controller = CreateController("store-1"); |
| 153 | + _brandServiceMock |
| 154 | + .Setup(s => s.GetAllBrands(null, "store-1", 0, 10, false)) |
| 155 | + .ReturnsAsync(new PagedList<Brand>([], 0, 10)); |
| 156 | + |
| 157 | + await controller.Brand(null, EmptyFilter()); |
| 158 | + |
| 159 | + _brandServiceMock.Verify(s => s.GetAllBrands(null, "store-1", 0, 10, false), Times.Once); |
| 160 | + } |
| 161 | +} |
0 commit comments