Skip to content

Commit a1c414e

Browse files
ARCH-001 Phase 25: consolidate Admin/Store PictureController (#826)
1 parent ecb7f73 commit a1c414e

6 files changed

Lines changed: 459 additions & 299 deletions

File tree

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
using Grand.Business.Core.Interfaces.Common.Security;
2+
using Grand.Business.Core.Interfaces.Storage;
3+
using Grand.Domain.Common;
4+
using Grand.Domain.Media;
5+
using Grand.Domain.Permissions;
6+
using Grand.Web.AdminShared.Controllers;
7+
using Microsoft.AspNetCore.Http;
8+
using Microsoft.AspNetCore.Mvc;
9+
using Microsoft.VisualStudio.TestTools.UnitTesting;
10+
using Moq;
11+
12+
namespace Grand.Web.Admin.Tests.Controllers;
13+
14+
[TestClass]
15+
public class BasePictureControllerTests
16+
{
17+
// Concrete subclass exists only to instantiate the abstract base for direct-call unit tests -
18+
// same pattern as BaseTaxCategoryControllerTests/BaseEmailAccountControllerTests.
19+
private class TestPictureController(
20+
IPictureService pictureService,
21+
IPermissionService permissionService,
22+
IMediaFileStore mediaFileStore,
23+
MediaSettings mediaSettings)
24+
: BasePictureController(pictureService, permissionService, mediaFileStore, mediaSettings);
25+
26+
private Mock<IPictureService> _pictureServiceMock = null!;
27+
private Mock<IPermissionService> _permissionServiceMock = null!;
28+
private Mock<IMediaFileStore> _mediaFileStoreMock = null!;
29+
private MediaSettings _mediaSettings = null!;
30+
31+
[TestInitialize]
32+
public void Setup()
33+
{
34+
_pictureServiceMock = new Mock<IPictureService>();
35+
_permissionServiceMock = new Mock<IPermissionService>();
36+
_mediaFileStoreMock = new Mock<IMediaFileStore>();
37+
_mediaSettings = new MediaSettings { AllowedFileTypes = ".jpg,.png" };
38+
}
39+
40+
private TestPictureController CreateController()
41+
{
42+
return new TestPictureController(
43+
_pictureServiceMock.Object,
44+
_permissionServiceMock.Object,
45+
_mediaFileStoreMock.Object,
46+
_mediaSettings);
47+
}
48+
49+
private static Mock<IFormFile> CreateFormFile(string fileName, string contentType = "image/jpeg")
50+
{
51+
var file = new Mock<IFormFile>();
52+
file.Setup(f => f.FileName).Returns(fileName);
53+
file.Setup(f => f.ContentType).Returns(contentType);
54+
file.Setup(f => f.Length).Returns(1);
55+
return file;
56+
}
57+
58+
// The controller's anonymous JSON payloads are internal to Grand.Web.AdminShared - `dynamic`
59+
// binding can't reach their properties across the assembly boundary, so read them via
60+
// reflection, same pattern as BaseDiscountControllerTests/BaseMerchandiseReturnControllerTests.
61+
private static T GetValue<T>(IActionResult result, string propertyName)
62+
{
63+
var value = ((JsonResult)result).Value!;
64+
return (T)value.GetType().GetProperty(propertyName)!.GetValue(value)!;
65+
}
66+
67+
[TestMethod]
68+
public async Task AsyncUpload_NullFile_ReturnsFailureJson()
69+
{
70+
var controller = CreateController();
71+
72+
var result = await controller.AsyncUpload(null);
73+
74+
Assert.IsFalse(GetValue<bool>(result, "success"));
75+
Assert.AreEqual("No file uploaded", GetValue<string>(result, "message"));
76+
_pictureServiceMock.Verify(p => p.InsertPicture(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(),
77+
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<Reference>(), It.IsAny<string>(),
78+
It.IsAny<bool>()), Times.Never);
79+
}
80+
81+
[TestMethod]
82+
public async Task AsyncUpload_ReferenceWithoutObjectId_ReturnsFailureJson()
83+
{
84+
var controller = CreateController();
85+
var file = CreateFormFile("picture.jpg");
86+
87+
var result = await controller.AsyncUpload(file.Object, Reference.Product, "");
88+
89+
Assert.IsFalse(GetValue<bool>(result, "success"));
90+
Assert.AreEqual("Please save form before upload new picture", GetValue<string>(result, "message"));
91+
}
92+
93+
[TestMethod]
94+
public async Task AsyncUpload_DisallowedFileType_ReturnsFailureJson()
95+
{
96+
var controller = CreateController();
97+
var file = CreateFormFile("picture.exe");
98+
99+
var result = await controller.AsyncUpload(file.Object);
100+
101+
Assert.IsFalse(GetValue<bool>(result, "success"));
102+
_pictureServiceMock.Verify(p => p.InsertPicture(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(),
103+
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<Reference>(), It.IsAny<string>(),
104+
It.IsAny<bool>()), Times.Never);
105+
}
106+
107+
[TestMethod]
108+
public async Task AsyncUpload_AllowedFileType_InsertsPictureAndReturnsSuccessJson()
109+
{
110+
var controller = CreateController();
111+
var file = CreateFormFile("picture.jpg");
112+
using var fileStream = new MemoryStream([1, 2, 3]);
113+
file.Setup(f => f.OpenReadStream()).Returns(fileStream);
114+
var insertedPicture = new Picture { Id = "pic-1" };
115+
_pictureServiceMock
116+
.Setup(p => p.InsertPicture(It.IsAny<byte[]>(), "image/jpeg", null,
117+
null, null, true, Reference.Product, "obj-1", false))
118+
.ReturnsAsync(insertedPicture);
119+
_pictureServiceMock
120+
.Setup(p => p.GetPictureUrl(insertedPicture, 100, true, null))
121+
.ReturnsAsync("/media/pic-1.jpg");
122+
123+
var result = await controller.AsyncUpload(file.Object, Reference.Product, "obj-1");
124+
125+
Assert.IsTrue(GetValue<bool>(result, "success"));
126+
Assert.AreEqual("pic-1", GetValue<string>(result, "pictureId"));
127+
Assert.AreEqual("/media/pic-1.jpg", GetValue<string>(result, "imageUrl"));
128+
}
129+
130+
[TestMethod]
131+
public async Task AsyncLogoUpload_PermissionDenied_ReturnsAccessDenied()
132+
{
133+
_permissionServiceMock.Setup(p => p.Authorize(StandardPermission.ManageSettings)).ReturnsAsync(false);
134+
var controller = CreateController();
135+
var file = CreateFormFile("logo.jpg");
136+
137+
var result = await controller.AsyncLogoUpload(file.Object);
138+
139+
var content = (ContentResult)result;
140+
Assert.AreEqual("Access denied", content.Content);
141+
_mediaFileStoreMock.Verify(m => m.GetFileInfo(It.IsAny<string>()), Times.Never);
142+
}
143+
144+
[TestMethod]
145+
public async Task AsyncLogoUpload_NullFile_ReturnsFailureJson()
146+
{
147+
_permissionServiceMock.Setup(p => p.Authorize(StandardPermission.ManageSettings)).ReturnsAsync(true);
148+
var controller = CreateController();
149+
150+
var result = await controller.AsyncLogoUpload(null);
151+
152+
Assert.IsFalse(GetValue<bool>(result, "success"));
153+
Assert.AreEqual("No file uploaded", GetValue<string>(result, "message"));
154+
}
155+
156+
[TestMethod]
157+
public async Task AsyncLogoUpload_DisallowedFileType_ReturnsFailureJson()
158+
{
159+
_permissionServiceMock.Setup(p => p.Authorize(StandardPermission.ManageSettings)).ReturnsAsync(true);
160+
var controller = CreateController();
161+
var file = CreateFormFile("logo.exe");
162+
163+
var result = await controller.AsyncLogoUpload(file.Object);
164+
165+
Assert.IsFalse(GetValue<bool>(result, "success"));
166+
Assert.AreEqual("File no allowed", GetValue<string>(result, "message"));
167+
_mediaFileStoreMock.Verify(m => m.GetFileInfo(It.IsAny<string>()), Times.Never);
168+
}
169+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System.Linq;
2+
using Grand.Web.Admin.Controllers;
3+
using Grand.Web.AdminShared.Controllers;
4+
using Grand.Web.Common.Filters;
5+
using Microsoft.AspNetCore.Mvc;
6+
using Microsoft.VisualStudio.TestTools.UnitTesting;
7+
8+
namespace Grand.Web.Admin.Tests.Controllers;
9+
10+
[TestClass]
11+
public class PictureControllerAttributeTests
12+
{
13+
[TestMethod]
14+
public void IsSubclassOfBasePictureController()
15+
{
16+
Assert.IsTrue(typeof(BasePictureController).IsAssignableFrom(typeof(PictureController)));
17+
Assert.AreEqual(typeof(BasePictureController), typeof(PictureController).BaseType);
18+
}
19+
20+
[TestMethod]
21+
public void HasAuthorizeAdminAttribute()
22+
{
23+
var attr = typeof(PictureController).GetCustomAttributes(typeof(AuthorizeAdminAttribute), inherit: false);
24+
Assert.AreEqual(1, attr.Length);
25+
}
26+
27+
[TestMethod]
28+
public void HasAreaAdminAttribute()
29+
{
30+
var attr = typeof(PictureController)
31+
.GetCustomAttributes(typeof(AreaAttribute), inherit: false)
32+
.Cast<AreaAttribute>().Single();
33+
Assert.AreEqual("Admin", attr.RouteValue);
34+
}
35+
36+
[TestMethod]
37+
public void HasAutoValidateAntiforgeryTokenAttribute()
38+
{
39+
var attr = typeof(PictureController)
40+
.GetCustomAttributes(typeof(AutoValidateAntiforgeryTokenAttribute), inherit: true);
41+
Assert.AreEqual(1, attr.Length);
42+
}
43+
44+
[TestMethod]
45+
public void HasAuthorizeMenuAttribute()
46+
{
47+
var attr = typeof(PictureController).GetCustomAttributes(typeof(AuthorizeMenuAttribute), inherit: false);
48+
Assert.AreEqual(1, attr.Length);
49+
}
50+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System.Linq;
2+
using Grand.Web.AdminShared.Controllers;
3+
using Grand.Web.Common.Filters;
4+
using Grand.Web.Store.Controllers;
5+
using Microsoft.AspNetCore.Mvc;
6+
using Microsoft.VisualStudio.TestTools.UnitTesting;
7+
8+
namespace Grand.Web.Store.Tests.Controllers;
9+
10+
[TestClass]
11+
public class PictureControllerAttributeTests
12+
{
13+
[TestMethod]
14+
public void IsSubclassOfBasePictureController()
15+
{
16+
Assert.IsTrue(typeof(BasePictureController).IsAssignableFrom(typeof(PictureController)));
17+
Assert.AreEqual(typeof(BasePictureController), typeof(PictureController).BaseType);
18+
}
19+
20+
[TestMethod]
21+
public void HasAuthorizeStoreAttribute()
22+
{
23+
var attr = typeof(PictureController).GetCustomAttributes(typeof(AuthorizeStoreAttribute), inherit: false);
24+
Assert.AreEqual(1, attr.Length);
25+
}
26+
27+
[TestMethod]
28+
public void HasAreaStoreAttribute()
29+
{
30+
var attr = typeof(PictureController)
31+
.GetCustomAttributes(typeof(AreaAttribute), inherit: false)
32+
.Cast<AreaAttribute>().Single();
33+
Assert.AreEqual("Store", attr.RouteValue);
34+
}
35+
36+
[TestMethod]
37+
public void HasAutoValidateAntiforgeryTokenAttribute()
38+
{
39+
var attr = typeof(PictureController)
40+
.GetCustomAttributes(typeof(AutoValidateAntiforgeryTokenAttribute), inherit: true);
41+
Assert.AreEqual(1, attr.Length);
42+
}
43+
44+
[TestMethod]
45+
public void HasAuthorizeMenuAttribute()
46+
{
47+
var attr = typeof(PictureController).GetCustomAttributes(typeof(AuthorizeMenuAttribute), inherit: false);
48+
Assert.AreEqual(1, attr.Length);
49+
}
50+
}

0 commit comments

Comments
 (0)