Skip to content
This repository was archived by the owner on Jul 3, 2025. It is now read-only.
Merged
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
102 changes: 102 additions & 0 deletions Tilemap2Animation.Test/Workflows/MainWorkflowTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -491,4 +491,106 @@ public async Task ExecuteAsync_WithNoValidTilesets_ThrowsException()
// Updated error message to match actual implementation
Assert.Contains("No tilesets could be loaded for the conversion", exception.Message);
}

[Fact]
public async Task ExecuteAsync_WithMultipleExtensions_ProcessesCorrectly()
{
// Arrange
var testFilePath = Path.Combine(Path.GetTempPath(), "test.gif.tmx");
var outputPath = Path.Combine(Path.GetTempPath(), "output.gif");

var options = new MainWorkflowOptions
{
InputFile = testFilePath,
OutputFile = outputPath,
FrameDelay = 100
};

var tilemap = new Tilemap
{
Width = 10,
Height = 10,
TileWidth = 16,
TileHeight = 16,
Layers = new List<TilemapLayer>
{
new TilemapLayer
{
Name = "Layer1",
Data = new TilemapLayerData { Encoding = "csv", Text = "1,2,3,4" }
}
},
Tilesets = new List<TilemapTileset>
{
new TilemapTileset { FirstGid = 1, Source = "test.tsx" }
}
};

var tileset = new Tileset
{
Image = new TilesetImage { Path = "test.png" }
};

var layerData = new List<uint> { 1, 2, 3, 4 };
var tilesetImage = new Image<Rgba32>(32, 32);
var frames = new List<Image<Rgba32>> { new Image<Rgba32>(16, 16) };
var delays = new List<int> { 100 };

_tilemapServiceMock.Setup(x => x.DeserializeTmxAsync(testFilePath)).ReturnsAsync(tilemap);
_tilemapServiceMock.Setup(x => x.ParseLayerData(It.IsAny<TilemapLayer>())).Returns(layerData);
_tilesetServiceMock.Setup(x => x.DeserializeTsxAsync(It.IsAny<string>())).ReturnsAsync(tileset);
_tilesetServiceMock.Setup(x => x.ResolveTilesetImagePath(It.IsAny<string>(), It.IsAny<string>())).Returns("test.png");
_tilesetImageServiceMock.Setup(x => x.LoadTilesetImageAsync(It.IsAny<string>())).ReturnsAsync(tilesetImage);
_tilesetImageServiceMock.Setup(x => x.ProcessTransparency(It.IsAny<Image<Rgba32>>(), It.IsAny<Tileset>())).Returns(tilesetImage);
_animationGeneratorServiceMock.Setup(x => x.GenerateAnimationFramesFromMultipleTilesetsAsync(
It.IsAny<Tilemap>(),
It.IsAny<List<(int FirstGid, Tileset? Tileset, Image<Rgba32>? TilesetImage)>>(),
It.IsAny<Dictionary<string, List<uint>>>(),
It.IsAny<int>()))
.ReturnsAsync((frames, delays));

try
{
// Act
await _sut.ExecuteAsync(options);

// Assert
_tilemapServiceMock.Verify(x => x.DeserializeTmxAsync(testFilePath), Times.Once);
_animationEncoderServiceMock.Verify(x => x.SaveAsGifAsync(
It.IsAny<List<Image<Rgba32>>>(),
It.IsAny<List<int>>(),
It.Is<string>(s => s == outputPath)),
Times.Once);
}
finally
{
tilesetImage.Dispose();
foreach (var frame in frames)
{
frame.Dispose();
}
}
}

[Fact]
public async Task ExecuteAsync_WithUnsupportedExtension_ThrowsArgumentException()
{
// Arrange
var testFilePath = Path.Combine(Path.GetTempPath(), "test.xyz");
var outputPath = Path.Combine(Path.GetTempPath(), "output.gif");

var options = new MainWorkflowOptions
{
InputFile = testFilePath,
OutputFile = outputPath,
FrameDelay = 100
};

// Act & Assert
var exception = await Assert.ThrowsAsync<ArgumentException>(() => _sut.ExecuteAsync(options));
Assert.Contains("Unsupported input file type", exception.Message);
Assert.Contains(".tmx", exception.Message);
Assert.Contains(".tsx", exception.Message);
Assert.Contains(".png", exception.Message);
}
}
17 changes: 14 additions & 3 deletions Tilemap2Animation/Workflows/MainWorkflow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,25 @@ public async Task ExecuteAsync(MainWorkflowOptions options)

var inputFile = Path.GetFullPath(options.InputFile);
var extension = Path.GetExtension(inputFile).ToLowerInvariant();
var fileName = Path.GetFileName(inputFile);
var supportedExtensions = new[] { ".tmx", ".tsx", ".png", ".jpg", ".jpeg", ".bmp" };

string? tmxInputFile = null;
string? tsxInputFile = null;
string? imageInputFile = null;

switch (extension)
// Find the last supported extension in the filename
var lastSupportedExtension = supportedExtensions
.Where(ext => fileName.EndsWith(ext, StringComparison.OrdinalIgnoreCase))
.OrderByDescending(ext => fileName.LastIndexOf(ext, StringComparison.OrdinalIgnoreCase))
.FirstOrDefault();

if (lastSupportedExtension == null)
{
throw new ArgumentException($"Unsupported input file type. File must end with one of: {string.Join(", ", supportedExtensions)}");
}

switch (lastSupportedExtension)
{
case ".tmx":
tmxInputFile = inputFile;
Expand All @@ -60,8 +73,6 @@ public async Task ExecuteAsync(MainWorkflowOptions options)
case ".bmp":
imageInputFile = inputFile;
break;
default:
throw new ArgumentException($"Unsupported input file type: {extension}");
}

Tilemap? tilemap = null;
Expand Down