Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -158,8 +158,11 @@ protected virtual async Task<string> GetThumbPhysicalPath(string thumbFileName)
/// <returns>Local picture thumb path</returns>
protected virtual string GetThumbUrl(string thumbFileName, string storeLocation = null)
{
storeLocation = !string.IsNullOrEmpty(storeLocation) ? storeLocation : "";
return _mediaFileStore.Combine(storeLocation, ImageThumbPath, thumbFileName);
var thumbPath = _mediaFileStore.Combine(ImageThumbPath, thumbFileName);
if (string.IsNullOrEmpty(storeLocation))
return thumbPath;

return new Uri(new Uri(storeLocation), thumbPath).ToString();
}
Copy link
Copy Markdown
Member

@KrzysztofPajak KrzysztofPajak Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

`
var thumbPath = _mediaFileStore.Combine(ImageThumbPath, thumbFileName);
if (string.IsNullOrEmpty(storeLocation))
return thumbPath;

    return new Uri(new Uri(storeLocation), thumbPath).ToString();

`
@copilot Maybe this way will be more professional?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in aa5a594. Using new Uri(new Uri(storeLocation), thumbPath).ToString() to properly combine the base URL with the relative thumb path.


/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,23 @@

namespace Grand.Business.Storage.Tests.Services;

/// <summary>
/// Exposes the protected GetThumbUrl method for testing.
/// </summary>
public class TestablePictureService(
IRepository<Picture> pictureRepository,
ILogger<PictureService> logger,
IMediator mediator,
ICacheBase cacheBase,
IMediaFileStore mediaFileStore,
MediaSettings mediaSettings,
StorageSettings storageSettings)
: PictureService(pictureRepository, logger, mediator, cacheBase, mediaFileStore, mediaSettings, storageSettings)
{
public string GetThumbUrlPublic(string thumbFileName, string storeLocation = null)
=> GetThumbUrl(thumbFileName, storeLocation);
}

[TestClass]
public class PictureServiceTests
{
Expand All @@ -22,6 +39,7 @@ public class PictureServiceTests
private Mock<IMediator> _mediatorMock;
private Mock<IRepository<Picture>> _repoMock;
private PictureService _service;
private TestablePictureService _testablePictureService;

private MediaSettings _settings;
private StorageSettings _storagesettings;
Expand All @@ -42,6 +60,8 @@ public void Init()
_storagesettings = new StorageSettings();
_service = new PictureService(_repoMock.Object, _logerMock.Object, _mediatorMock.Object, _cacheMock.Object,
_mediaFileStoreMock.Object, _settings, _storagesettings);
_testablePictureService = new TestablePictureService(_repoMock.Object, _logerMock.Object,
_mediatorMock.Object, _cacheMock.Object, _mediaFileStoreMock.Object, _settings, _storagesettings);
}

[TestMethod]
Expand Down Expand Up @@ -139,4 +159,28 @@ public async Task DeletePicture_ValidArguments_InvokeRepositoryAndPublishEvent()
_repoMock.Verify(c => c.DeleteAsync(It.IsAny<Picture>()), Times.Once);
_mediatorMock.Verify(c => c.Publish(It.IsAny<EntityDeleted<Picture>>(), default), Times.Once);
}

[TestMethod]
public void GetThumbUrl_WithAbsoluteStoreLocation_ReturnsValidAbsoluteUrl()
{
const string storeLocation = "https://example.com/";
const string thumbFileName = "sample_123.jpeg";

var result = _testablePictureService.GetThumbUrlPublic(thumbFileName, storeLocation);

Assert.IsTrue(result.StartsWith("https://"), $"Expected URL to start with 'https://' but got: {result}");
Assert.IsTrue(result.Contains(thumbFileName), $"Expected URL to contain thumb filename but got: {result}");
Assert.IsFalse(result.StartsWith("/https://"), $"URL must not have a leading slash before the scheme: {result}");
}

[TestMethod]
public void GetThumbUrl_WithNoStoreLocation_ReturnsRelativePath()
{
const string thumbFileName = "sample_123.jpeg";

var result = _testablePictureService.GetThumbUrlPublic(thumbFileName);

Assert.IsTrue(result.StartsWith("/"), $"Expected relative path to start with '/' but got: {result}");
Assert.IsTrue(result.Contains(thumbFileName), $"Expected path to contain thumb filename but got: {result}");
}
}
Loading