Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
10e037c
Share the product controller test fixture through a base class
Oct 21, 2026
b461262
Move the product bids tab into its own controller
Oct 22, 2026
cef521a
Move the product reservations tab into its own controller
Oct 22, 2026
3e570fe
Move the product pictures tab into its own controller
Oct 22, 2026
07a419e
Move the product specification attributes tab into its own controller
Oct 22, 2026
6971589
Move the product categories and collections tab into their own contro…
Oct 22, 2026
fe53fc6
Move the related products tab into its own controller
Oct 22, 2026
6a3801f
Move the bundle and associated products tabs into their own controllers
Oct 22, 2026
338012d
Move the product prices tab into its own controller
Oct 22, 2026
0523856
Move the product attributes tab into its own controller
Oct 22, 2026
40d4434
Move the attribute combinations tab into its own controller
Oct 22, 2026
8d7d576
Drop the tab dependencies left on the product controllers
Oct 22, 2026
49f949e
Check the panel attributes and Vendor hooks of every product controller
Oct 22, 2026
d35270a
Move the product specification view-model logic into its own service
Oct 22, 2026
0d44a38
Move the product pictures view-model logic into its own service
Oct 22, 2026
d7f87c0
Move the product categories view-model logic into its own service
Oct 22, 2026
73bde06
Move the product collections view-model logic into its own service
Oct 22, 2026
f5548ef
Move the product bids view-model logic into its own service
Oct 22, 2026
4e0ed82
Move the product prices view-model logic into its own service
Oct 22, 2026
9561d12
Move the related, bundle and associated products view-model logic int…
Oct 22, 2026
8613c61
Move the product attributes view-model logic into its own service
Oct 22, 2026
26fec1a
Move the attribute combinations view-model logic into its own service
Oct 22, 2026
edf4651
Drop the tab dependencies left on the product view-model service
Oct 22, 2026
123522a
Remove the stray bash.exe.stackdump from the Admin tests
Oct 22, 2026
c254227
Recalculate attribute combination stock on the loaded product
Oct 22, 2026
886ff13
Move the add-product popup view-model logic into its own service
Oct 22, 2026
88cfa7a
Merge remote-tracking branch 'origin/develop' into refactor/split-bas…
Oct 22, 2026
933a032
Set the blog post dates after insert in the tag paging test
Oct 22, 2026
f125a91
Merge the final state of the product tab controllers split (#974)
Oct 22, 2026
a4405d0
Merge remote-tracking branch 'origin/develop' into refactor/split-pro…
Oct 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ public class BaseProductAssociatedControllerTests : ProductControllerTestsBase<B
// BaseProductAssociatedController is abstract. This minimal subclass exists only so the actions under test
// can be invoked directly.
public class TestProductAssociatedController(
IProductViewModelService productViewModelService,
IProductAddPopupViewModelService productAddPopupViewModelService,
IProductAssociatedViewModelService productAssociatedViewModelService,
IProductService productService,
IRequestTranslationService translationService,
IAdminDataScope<Product> scope)
: BaseProductAssociatedController(productViewModelService, productService, translationService, scope);
: BaseProductAssociatedController(productAddPopupViewModelService, productAssociatedViewModelService, productService, translationService, scope);

protected override TestProductAssociatedController CreateController() => new(
_productViewModelServiceMock.Object,
_productAddPopupViewModelServiceMock.Object,
_productAssociatedViewModelServiceMock.Object,
_productServiceMock.Object,
_translationServiceMock.Object,
_scopeMock.Object);
Expand Down Expand Up @@ -134,7 +136,7 @@ public async Task AssociatedProductDelete_ScopeDeniesAccess_ReturnsErrorJson_Doe

Assert.IsInstanceOfType<JsonResult>(result);
_translationServiceMock.Verify(t => t.GetResource("Admin.Catalog.Products.Permissions"), Times.Once);
_productViewModelServiceMock.Verify(s => s.DeleteAssociatedProduct(It.IsAny<Product>()), Times.Never);
_productAssociatedViewModelServiceMock.Verify(s => s.DeleteAssociatedProduct(It.IsAny<Product>()), Times.Never);
}

[TestMethod]
Expand All @@ -148,7 +150,7 @@ public async Task AssociatedProductDelete_ScopeGrantsAccess_ValidModel_Deletes()
var result = await _controller.AssociatedProductDelete(model);

Assert.IsInstanceOfType<JsonResult>(result);
_productViewModelServiceMock.Verify(s => s.DeleteAssociatedProduct(product), Times.Once);
_productAssociatedViewModelServiceMock.Verify(s => s.DeleteAssociatedProduct(product), Times.Once);
}

// --- AssociatedProductAddPopup (GET) -------------------------------------------------------------
Expand All @@ -157,7 +159,7 @@ public async Task AssociatedProductDelete_ScopeGrantsAccess_ValidModel_Deletes()
public async Task AssociatedProductAddPopupGet_CallsPrepareAssociatedProductModel()
{
// PrepareAssociatedProductModel() now reads scope internally (Task 9).
_productViewModelServiceMock.Setup(s => s.PrepareAssociatedProductModel())
_productAddPopupViewModelServiceMock.Setup(s => s.PrepareAssociatedProductModel())
.ReturnsAsync(new ProductModel.AddAssociatedProductModel());

var result = await _controller.AssociatedProductAddPopup("p1") as ViewResult;
Expand All @@ -166,7 +168,7 @@ public async Task AssociatedProductAddPopupGet_CallsPrepareAssociatedProductMode
var model = result.Model as ProductModel.AddAssociatedProductModel;
Assert.IsNotNull(model);
Assert.AreEqual("p1", model.ProductId);
_productViewModelServiceMock.Verify(s => s.PrepareAssociatedProductModel(), Times.Once);
_productAddPopupViewModelServiceMock.Verify(s => s.PrepareAssociatedProductModel(), Times.Once);
}

// --- AssociatedProductAddPopupList ---------------------------------------------------------------
Expand All @@ -175,7 +177,7 @@ public async Task AssociatedProductAddPopupGet_CallsPrepareAssociatedProductMode
public async Task AssociatedProductAddPopupList_UsesScopeDefaultStoreId()
{
_scopeMock.Setup(s => s.DefaultStoreId).Returns("store-1");
_productViewModelServiceMock
_productAddPopupViewModelServiceMock
.Setup(s => s.PrepareProductModel(It.IsAny<ProductModel.AddAssociatedProductModel>(), 0, 10))
.ReturnsAsync((new List<ProductModel>(), 0));

Expand All @@ -191,7 +193,7 @@ public async Task AssociatedProductAddPopupList_UsesScopeDefaultStoreId()
public async Task AssociatedProductAddPopupList_NoDefaultStoreId_DoesNotOverrideModelSearchStoreId()
{
_scopeMock.Setup(s => s.DefaultStoreId).Returns((string)null);
_productViewModelServiceMock
_productAddPopupViewModelServiceMock
.Setup(s => s.PrepareProductModel(It.IsAny<ProductModel.AddAssociatedProductModel>(), 0, 10))
.ReturnsAsync((new List<ProductModel>(), 0));

Expand Down Expand Up @@ -227,7 +229,7 @@ public async Task AssociatedProductAddPopupPost_ScopeDeniesAccessToParent_Return

Assert.IsInstanceOfType<ContentResult>(result);
_translationServiceMock.Verify(t => t.GetResource("Admin.Catalog.Products.Permissions"), Times.Once);
_productViewModelServiceMock.Verify(s => s.InsertAssociatedProductModel(It.IsAny<ProductModel.AddAssociatedProductModel>()), Times.Never);
_productAssociatedViewModelServiceMock.Verify(s => s.InsertAssociatedProductModel(It.IsAny<ProductModel.AddAssociatedProductModel>()), Times.Never);
}

[TestMethod]
Expand All @@ -247,7 +249,7 @@ public async Task AssociatedProductAddPopupPost_ScopeGrantsAccess_AllSelectedIds
Assert.IsNotNull(content);
Assert.AreEqual("", content.Content);
CollectionAssert.AreEqual(new[] { "a1" }, model.SelectedProductIds);
_productViewModelServiceMock.Verify(s => s.InsertAssociatedProductModel(model), Times.Once);
_productAssociatedViewModelServiceMock.Verify(s => s.InsertAssociatedProductModel(model), Times.Once);
}

[TestMethod]
Expand All @@ -268,7 +270,7 @@ public async Task AssociatedProductAddPopupPost_ScopeGrantsAccessToParent_Filter

Assert.IsInstanceOfType<ContentResult>(result);
CollectionAssert.AreEqual(new[] { "a1" }, model.SelectedProductIds);
_productViewModelServiceMock.Verify(s => s.InsertAssociatedProductModel(model), Times.Once);
_productAssociatedViewModelServiceMock.Verify(s => s.InsertAssociatedProductModel(model), Times.Once);
}

[TestMethod]
Expand All @@ -285,7 +287,7 @@ public async Task AssociatedProductAddPopupPost_AllSelectedIdsDenied_DoesNotInse
var result = await _controller.AssociatedProductAddPopup(model);

Assert.IsInstanceOfType<ContentResult>(result);
_productViewModelServiceMock.Verify(s => s.InsertAssociatedProductModel(It.IsAny<ProductModel.AddAssociatedProductModel>()), Times.Never);
_productAssociatedViewModelServiceMock.Verify(s => s.InsertAssociatedProductModel(It.IsAny<ProductModel.AddAssociatedProductModel>()), Times.Never);
}

[TestMethod]
Expand All @@ -295,7 +297,7 @@ public async Task AssociatedProductAddPopupPost_ScopeGrantsAccess_InvalidModel_R
_productServiceMock.Setup(p => p.GetProductById("p1", false)).ReturnsAsync(parent);
_scopeMock.Setup(s => s.HasAccess(parent)).ReturnsAsync(true);
var reprepared = new ProductModel.AddAssociatedProductModel();
_productViewModelServiceMock.Setup(s => s.PrepareAssociatedProductModel()).ReturnsAsync(reprepared);
_productAddPopupViewModelServiceMock.Setup(s => s.PrepareAssociatedProductModel()).ReturnsAsync(reprepared);
var model = new ProductModel.AddAssociatedProductModel { ProductId = "p1" };
_controller.ModelState.AddModelError("x", "error");

Expand All @@ -304,6 +306,6 @@ public async Task AssociatedProductAddPopupPost_ScopeGrantsAccess_InvalidModel_R
var view = result as ViewResult;
Assert.IsNotNull(view);
Assert.AreSame(reprepared, view.Model);
_productViewModelServiceMock.Verify(s => s.InsertAssociatedProductModel(It.IsAny<ProductModel.AddAssociatedProductModel>()), Times.Never);
_productAssociatedViewModelServiceMock.Verify(s => s.InsertAssociatedProductModel(It.IsAny<ProductModel.AddAssociatedProductModel>()), Times.Never);
}
}
Loading
Loading