From 943431c131acc520ebacc27dbc2ad100f642ef0f Mon Sep 17 00:00:00 2001
From: Sven <40752681+NeoCoderMatrix86@users.noreply.github.com>
Date: Mon, 9 Mar 2026 16:41:22 +0100
Subject: [PATCH 1/4] fix upload dialog
---
AudioCuesheetEditor/Model/IO/FileUpload.cs | 25 +++++
.../Services/IO/FileInputManager.cs | 93 ++++++++++++-------
.../Services/IO/IFileInputManager.cs | 28 ++++--
.../Services/IO/ImportManager.cs | 53 ++++-------
AudioCuesheetEditor/Shared/AppBar.razor | 4 +-
.../Shared/Cuesheet/CuesheetData.razor | 29 ++++--
.../Shared/Cuesheet/EditSections.razor | 2 +-
.../Shared/Inputs/FileDropOverlay.razor | 8 +-
.../Shared/Inputs/TextField.razor | 5 +-
9 files changed, 157 insertions(+), 90 deletions(-)
create mode 100644 AudioCuesheetEditor/Model/IO/FileUpload.cs
diff --git a/AudioCuesheetEditor/Model/IO/FileUpload.cs b/AudioCuesheetEditor/Model/IO/FileUpload.cs
new file mode 100644
index 00000000..a8df1ee7
--- /dev/null
+++ b/AudioCuesheetEditor/Model/IO/FileUpload.cs
@@ -0,0 +1,25 @@
+//This file is part of AudioCuesheetEditor.
+
+//AudioCuesheetEditor is free software: you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation, either version 3 of the License, or
+//(at your option) any later version.
+
+//AudioCuesheetEditor is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+
+//You should have received a copy of the GNU General Public License
+//along with Foobar. If not, see
+//.
+namespace AudioCuesheetEditor.Model.IO
+{
+ public class FileUpload(string name, string contentType, string? content = null, string? objectUrl = null)
+ {
+ public string Name { get; set; } = name;
+ public string ContentType { get; set; } = contentType;
+ public string? Content { get; set; } = content;
+ public string? ObjectUrl { get; set; } = objectUrl;
+ }
+}
diff --git a/AudioCuesheetEditor/Services/IO/FileInputManager.cs b/AudioCuesheetEditor/Services/IO/FileInputManager.cs
index a47eb4f5..6bbabfae 100644
--- a/AudioCuesheetEditor/Services/IO/FileInputManager.cs
+++ b/AudioCuesheetEditor/Services/IO/FileInputManager.cs
@@ -28,12 +28,12 @@ public class FileInputManager(IJSRuntime jsRuntime, HttpClient httpClient, ILogg
private readonly HttpClient _httpClient = httpClient;
private readonly ILogger _logger = logger;
- public AudioCodec? GetAudioCodec(IBrowserFile browserFile)
+ public AudioCodec? GetAudioCodec(string? fileContentType, string fileName)
{
AudioCodec? foundAudioCodec = null;
- var extension = Path.GetExtension(browserFile.Name);
+ var extension = Path.GetExtension(fileName);
// First search with mime type and file extension
- var audioCodecsFound = Audiofile.AudioCodecs.Where(x => x.MimeType.Equals(browserFile.ContentType, StringComparison.OrdinalIgnoreCase) && x.FileExtension.Equals(extension, StringComparison.OrdinalIgnoreCase));
+ var audioCodecsFound = Audiofile.AudioCodecs.Where(x => x.MimeType.Equals(fileContentType, StringComparison.OrdinalIgnoreCase) && x.FileExtension.Equals(extension, StringComparison.OrdinalIgnoreCase));
if (audioCodecsFound.Count() <= 1)
{
foundAudioCodec = audioCodecsFound.FirstOrDefault();
@@ -41,63 +41,62 @@ public class FileInputManager(IJSRuntime jsRuntime, HttpClient httpClient, ILogg
if (foundAudioCodec == null)
{
// Second search with mime type or file extension
- audioCodecsFound = Audiofile.AudioCodecs.Where(x => x.MimeType.Equals(browserFile.ContentType, StringComparison.OrdinalIgnoreCase) || x.FileExtension.Equals(extension, StringComparison.OrdinalIgnoreCase));
+ audioCodecsFound = Audiofile.AudioCodecs.Where(x => x.MimeType.Equals(fileContentType, StringComparison.OrdinalIgnoreCase) || x.FileExtension.Equals(extension, StringComparison.OrdinalIgnoreCase));
foundAudioCodec = audioCodecsFound.FirstOrDefault();
}
return foundAudioCodec;
}
- public bool IsValidAudiofile(IBrowserFile browserFile)
+ public bool IsValidAudiofile(string? fileContentType, string fileName)
{
- var codec = GetAudioCodec(browserFile);
- return codec != null;
+ return GetAudioCodec(fileContentType, fileName) != null;
}
- public Boolean CheckFileMimeType(IBrowserFile file, String mimeType, IEnumerable fileExtensions)
+ public bool CheckFileMimeType(string? fileContentType, string fileName, string mimeType, IEnumerable fileExtensions)
{
+ //TODO: Tests
if (_logger.IsEnabled(LogLevel.Debug))
{
- _logger.LogDebug("CheckFileMimeType called with file: file.Name: '{FileName}', file.ContentType: '{ContentType}', mimeType: '{MimeType}', fileExtensions: '{fileExtensions}'", file.Name, file.ContentType, mimeType, fileExtensions);
+ _logger.LogDebug("CheckFileMimeType called with file: file.Name: '{FileName}', file.ContentType: '{ContentType}', mimeType: '{MimeType}', fileExtensions: '{fileExtensions}'", fileName, fileContentType, mimeType, fileExtensions);
}
Boolean fileMimeTypeMatches = false;
- if ((file != null) && (String.IsNullOrEmpty(mimeType) == false))
+ if (String.IsNullOrEmpty(mimeType) == false)
{
- if (String.IsNullOrEmpty(file.ContentType) == false)
+ if (String.IsNullOrEmpty(fileContentType) == false)
{
if (mimeType.EndsWith("/*"))
{
var mainType = mimeType[..^1];
- fileMimeTypeMatches = file.ContentType.StartsWith(mainType, StringComparison.CurrentCultureIgnoreCase);
+ fileMimeTypeMatches = fileContentType.StartsWith(mainType, StringComparison.CurrentCultureIgnoreCase);
}
else
{
- fileMimeTypeMatches = file.ContentType.Equals(mimeType, StringComparison.CurrentCultureIgnoreCase);
+ fileMimeTypeMatches = fileContentType.Equals(mimeType, StringComparison.CurrentCultureIgnoreCase);
}
}
if ((fileMimeTypeMatches == false) && (fileExtensions.Any()))
{
//Try to find by file extension
- var extension = Path.GetExtension(file.Name);
+ var extension = Path.GetExtension(fileName);
fileMimeTypeMatches = fileExtensions.Any(x => x.Equals(extension, StringComparison.CurrentCultureIgnoreCase));
}
}
return fileMimeTypeMatches;
}
- public async Task CreateAudiofileAsync(String? fileInputId, IBrowserFile? browserFile, Action>? afterContentStreamLoaded = null)
+ public async Task CreateAudiofileAsync(FileUpload fileUpload, Action>? afterContentStreamLoaded = null)
{
Audiofile? audiofile = null;
- if ((String.IsNullOrEmpty(fileInputId) == false) && (browserFile != null))
+ if (fileUpload.ObjectUrl != null)
{
// Check file mime type
- var codec = GetAudioCodec(browserFile);
+ var codec = GetAudioCodec(fileUpload.ContentType, fileUpload.Name);
if (codec != null)
{
- var audioFileObjectURL = await _jsRuntime.InvokeAsync("getObjectURLFromMudFileUpload", fileInputId);
- audiofile = new Audiofile(browserFile.Name, audioFileObjectURL, codec);
- if (String.IsNullOrEmpty(audioFileObjectURL) == false)
+ audiofile = new Audiofile(fileUpload.Name, fileUpload.ObjectUrl, codec);
+ if (String.IsNullOrEmpty(fileUpload.ObjectUrl) == false)
{
- var request = new HttpRequestMessage(HttpMethod.Get, audioFileObjectURL);
+ var request = new HttpRequestMessage(HttpMethod.Get, fileUpload.ObjectUrl);
//TODO: Enable when https://github.com/NeoCoderMatrix86/AudioCuesheetEditor/issues/524 gets done
request.SetBrowserRequestStreamingEnabled(false);
@@ -119,27 +118,25 @@ public Boolean CheckFileMimeType(IBrowserFile file, String mimeType, IEnumerable
return audiofile;
}
- public CDTextfile? CreateCDTextfile(IBrowserFile? browserFile)
+ public CDTextfile? CreateCDTextfile(string? fileContentType, string fileName)
{
- CDTextfile? cdTextfile = null;
- if (browserFile != null)
+ CDTextfile? cdTextfile;
+ if (CheckFileMimeType(fileContentType, fileName, FileMimeTypes.Text, [FileExtensions.CDTextfile]))
{
- if (CheckFileMimeType(browserFile, FileMimeTypes.Text, [FileExtensions.CDTextfile]))
- {
- cdTextfile = new CDTextfile(browserFile.Name);
- }
- else
- {
- throw new ArgumentException("The cdtextfile provided is not of a valid type.");
- }
+ cdTextfile = new CDTextfile(fileName);
+ }
+ else
+ {
+ throw new ArgumentException("The cdtextfile provided is not of a valid type.");
}
return cdTextfile;
}
///
- public bool IsValidForImportView(IBrowserFile browserFile)
+ public bool IsValidForImportView(string? fileContentType, string fileName)
{
- return CheckFileMimeType(browserFile, FileMimeTypes.Text, [FileExtensions.Text, FileExtensions.HTML]);
+ //TODO: Tests
+ return CheckFileMimeType(fileContentType, fileName, FileMimeTypes.Text, [FileExtensions.Text, FileExtensions.HTML]);
}
///
@@ -148,5 +145,33 @@ public async Task ReadFileContentAsync(IBrowserFile browserFile)
var fileContent = new StreamContent(browserFile.OpenReadStream());
return await fileContent.ReadAsStringAsync();
}
+
+ ///
+ public async Task> CreateFileUploadsAsync(IReadOnlyList browserFiles, string? fileInputId = null)
+ {
+ //TODO: Tests
+ List fileUploads = [];
+ foreach (var file in browserFiles)
+ {
+ if (CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Projectfile, [FileExtensions.Projectfile])
+ || CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Cuesheet, [FileExtensions.Cuesheet])
+ || IsValidForImportView(file.ContentType, file.Name)
+ || IsValidAudiofile(file.ContentType, file.Name))
+ {
+ string? content = null;
+ string? objectUrl = null;
+ if (IsValidAudiofile(file.ContentType, file.Name))
+ {
+ objectUrl = await _jsRuntime.InvokeAsync("getObjectURLFromMudFileUpload", fileInputId);
+ }
+ else
+ {
+ content = await ReadFileContentAsync(file);
+ }
+ fileUploads.Add(new(file.Name, file.ContentType, content, objectUrl));
+ }
+ }
+ return fileUploads;
+ }
}
}
diff --git a/AudioCuesheetEditor/Services/IO/IFileInputManager.cs b/AudioCuesheetEditor/Services/IO/IFileInputManager.cs
index e5d00d13..026ed5d4 100644
--- a/AudioCuesheetEditor/Services/IO/IFileInputManager.cs
+++ b/AudioCuesheetEditor/Services/IO/IFileInputManager.cs
@@ -15,6 +15,7 @@
//.
using AudioCuesheetEditor.Model.AudioCuesheet;
+using AudioCuesheetEditor.Model.IO;
using AudioCuesheetEditor.Model.IO.Audio;
using Microsoft.AspNetCore.Components.Forms;
@@ -22,22 +23,37 @@ namespace AudioCuesheetEditor.Services.IO
{
public interface IFileInputManager
{
- bool IsValidAudiofile(IBrowserFile browserFile);
- AudioCodec? GetAudioCodec(IBrowserFile browserFile);
- bool CheckFileMimeType(IBrowserFile file, string mimeType, IEnumerable fileExtensions);
- Task CreateAudiofileAsync(string? fileInputId, IBrowserFile? browserFile, Action>? afterContentStreamLoaded = null);
- CDTextfile? CreateCDTextfile(IBrowserFile? browserFile);
+ bool IsValidAudiofile(string? fileContentType, string fileName);
+ AudioCodec? GetAudioCodec(string? fileContentType, string fileName);
+ ///
+ /// Checks if a file content type and name matches given parameters
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ bool CheckFileMimeType(string? fileContentType, string fileName, string mimeType, IEnumerable fileExtensions);
+ Task CreateAudiofileAsync(FileUpload fileUpload, Action>? afterContentStreamLoaded = null);
+ CDTextfile? CreateCDTextfile(string? fileContentType, string fileName);
///
/// Checks if the file can be used for the import view
///
///
///
- bool IsValidForImportView(IBrowserFile browserFile);
+ bool IsValidForImportView(string? fileContentType, string fileName);
///
/// Reads the browser file and gets the file content as string
///
///
///
Task ReadFileContentAsync(IBrowserFile browserFile);
+ ///
+ /// Generates file upload references for files
+ ///
+ ///
+ ///
+ ///
+ Task> CreateFileUploadsAsync(IReadOnlyList browserFiles, string? fileInputId = null);
}
}
\ No newline at end of file
diff --git a/AudioCuesheetEditor/Services/IO/ImportManager.cs b/AudioCuesheetEditor/Services/IO/ImportManager.cs
index 15a32fb3..6817670f 100644
--- a/AudioCuesheetEditor/Services/IO/ImportManager.cs
+++ b/AudioCuesheetEditor/Services/IO/ImportManager.cs
@@ -121,59 +121,47 @@ public void ImportCuesheet()
}
}
- public async Task UploadFilesAsync(IEnumerable files, String? fileInputId = null)
+ public async Task UploadFilesAsync(IEnumerable files)
{
var stopwatch = Stopwatch.StartNew();
var invalidFiles = new List();
foreach (var file in files)
{
- if (_fileInputManager.CheckFileMimeType(file, FileMimeTypes.Projectfile, [FileExtensions.Projectfile])
- || _fileInputManager.CheckFileMimeType(file, FileMimeTypes.Cuesheet, [FileExtensions.Cuesheet])
- || _fileInputManager.IsValidForImportView(file)
- || _fileInputManager.IsValidAudiofile(file))
+ if (_fileInputManager.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Projectfile, [FileExtensions.Projectfile])
+ || _fileInputManager.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Cuesheet, [FileExtensions.Cuesheet])
+ || _fileInputManager.IsValidForImportView(file.ContentType, file.Name)
+ || _fileInputManager.IsValidAudiofile(file.ContentType, file.Name))
{
- if (_fileInputManager.CheckFileMimeType(file, FileMimeTypes.Projectfile, [FileExtensions.Projectfile]))
+ if (_fileInputManager.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Projectfile, [FileExtensions.Projectfile]))
{
- var fileContent = await ReadFileContentAsync(file);
- fileContent.Position = 0;
- using var reader = new StreamReader(fileContent);
- var stringFileContent = reader.ReadToEnd();
_sessionStateContainer.Importfile = new Importfile()
{
- FileContent = stringFileContent,
- FileContentRecognized = stringFileContent,
+ FileContent = file.Content,
+ FileContentRecognized = file.Content,
FileType = ImportFileType.ProjectFile
};
}
- if (_fileInputManager.CheckFileMimeType(file, FileMimeTypes.Cuesheet, [FileExtensions.Cuesheet]))
+ if (_fileInputManager.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Cuesheet, [FileExtensions.Cuesheet]))
{
- var fileContent = await ReadFileContentAsync(file);
- fileContent.Position = 0;
- using var reader = new StreamReader(fileContent);
- var stringFileContent = reader.ReadToEnd();
_sessionStateContainer.Importfile = new Importfile()
{
- FileContent = stringFileContent,
- FileContentRecognized = stringFileContent,
+ FileContent = file.Content,
+ FileContentRecognized = file.Content,
FileType = ImportFileType.Cuesheet
};
}
- if (_fileInputManager.IsValidForImportView(file))
+ if (_fileInputManager.IsValidForImportView(file.ContentType, file.Name))
{
- var fileContent = await ReadFileContentAsync(file);
- fileContent.Position = 0;
- using var reader = new StreamReader(fileContent);
- var stringFileContent = reader.ReadToEnd();
_sessionStateContainer.Importfile = new Importfile()
{
- FileContent = stringFileContent,
- FileContentRecognized = stringFileContent,
+ FileContent = file.Content,
+ FileContentRecognized = file.Content,
FileType = ImportFileType.Textfile
};
}
- if (_fileInputManager.IsValidAudiofile(file))
+ if (_fileInputManager.IsValidAudiofile(file.ContentType, file.Name))
{
- var audioFile = await _fileInputManager.CreateAudiofileAsync(fileInputId, file);
+ var audioFile = await _fileInputManager.CreateAudiofileAsync(file);
_sessionStateContainer.ImportAudiofile = audioFile;
}
}
@@ -190,15 +178,6 @@ public async Task UploadFilesAsync(IEnumerable files, String? file
}
}
- private static async Task ReadFileContentAsync(IBrowserFile file)
- {
- var fileContent = new MemoryStream();
- var stream = file.OpenReadStream();
- await stream.CopyToAsync(fileContent);
- stream.Close();
- return fileContent;
- }
-
private static void CopyCuesheet(Cuesheet target, ICuesheet cuesheetToCopy)
{
target.IsImporting = true;
diff --git a/AudioCuesheetEditor/Shared/AppBar.razor b/AudioCuesheetEditor/Shared/AppBar.razor
index d4f89c8c..395d5e3d 100644
--- a/AudioCuesheetEditor/Shared/AppBar.razor
+++ b/AudioCuesheetEditor/Shared/AppBar.razor
@@ -25,6 +25,7 @@ along with Foobar. If not, see
@inject IJSRuntime _jsRuntime
@inject HotKeys _hotKeys
@inject ImportManager _importManager
+@inject IFileInputManager _fileInputManager
@@ -229,7 +230,8 @@ along with Foobar. If not, see
async Task FileUploaded(IBrowserFile file)
{
- await _importManager.UploadFilesAsync([file]);
+ var fileUploads = await _fileInputManager.CreateFileUploadsAsync([file]);
+ await _importManager.UploadFilesAsync(fileUploads);
}
async Task ShowHotkeysDialog()
diff --git a/AudioCuesheetEditor/Shared/Cuesheet/CuesheetData.razor b/AudioCuesheetEditor/Shared/Cuesheet/CuesheetData.razor
index 4d44b0a3..61605a5a 100644
--- a/AudioCuesheetEditor/Shared/Cuesheet/CuesheetData.razor
+++ b/AudioCuesheetEditor/Shared/Cuesheet/CuesheetData.razor
@@ -111,14 +111,22 @@ along with Foobar. If not, see
fileInputAudiofileErrorText = null;
try
{
- Cuesheet.Audiofile = await _fileInputManager.CreateAudiofileAsync(fileInputAudiofileId, browserFile, x =>
+ if (browserFile != null)
{
- if (Cuesheet.RecalculateLastTrackEnd())
+ var fileUpload = await _fileInputManager.CreateFileUploadsAsync([browserFile], fileInputAudiofileId);
+ Cuesheet.Audiofile = await _fileInputManager.CreateAudiofileAsync(fileUpload.Single(), x =>
{
- TraceChangeManager.MergeLastEditWithEdit(x => x.Changes.All(y => y.TraceableObject == Cuesheet && y.TraceableChange.PropertyName == nameof(Audiofile)));
- }
- StateHasChanged();
- });
+ if (Cuesheet.RecalculateLastTrackEnd())
+ {
+ TraceChangeManager.MergeLastEditWithEdit(x => x.Changes.All(y => y.TraceableObject == Cuesheet && y.TraceableChange.PropertyName == nameof(Audiofile)));
+ }
+ StateHasChanged();
+ });
+ }
+ else
+ {
+ Cuesheet.Audiofile = null;
+ }
}
catch(ArgumentException ae)
{
@@ -157,7 +165,14 @@ along with Foobar. If not, see
fileInputCDTextfileErrorText = null;
try
{
- Cuesheet.CDTextfile = _fileInputManager.CreateCDTextfile(browserFile);
+ if (browserFile != null)
+ {
+ Cuesheet.CDTextfile = _fileInputManager.CreateCDTextfile(browserFile.ContentType, browserFile.Name);
+ }
+ else
+ {
+ Cuesheet.CDTextfile = null;
+ }
}
catch (ArgumentException ae)
{
diff --git a/AudioCuesheetEditor/Shared/Cuesheet/EditSections.razor b/AudioCuesheetEditor/Shared/Cuesheet/EditSections.razor
index d1abd5cb..2c998de5 100644
--- a/AudioCuesheetEditor/Shared/Cuesheet/EditSections.razor
+++ b/AudioCuesheetEditor/Shared/Cuesheet/EditSections.razor
@@ -142,7 +142,7 @@ along with Foobar. If not, see
void AudiofileSelected(CuesheetSection section, IBrowserFile? browserFile)
{
- if ((browserFile != null) && (_fileInputManager.IsValidAudiofile(browserFile) == true))
+ if ((browserFile != null) && (_fileInputManager.IsValidAudiofile(browserFile.ContentType, browserFile.Name) == true))
{
section.AudiofileName = browserFile?.Name;
}
diff --git a/AudioCuesheetEditor/Shared/Inputs/FileDropOverlay.razor b/AudioCuesheetEditor/Shared/Inputs/FileDropOverlay.razor
index 2f22ee2f..deb044b1 100644
--- a/AudioCuesheetEditor/Shared/Inputs/FileDropOverlay.razor
+++ b/AudioCuesheetEditor/Shared/Inputs/FileDropOverlay.razor
@@ -23,6 +23,7 @@ along with Foobar. If not, see
@inject IStringLocalizer _localizer
@inject ImportManager _importManager
@inject DialogManager _dialogManager
+@inject IFileInputManager _fileInputManager
@@ -42,7 +43,7 @@ along with Foobar. If not, see
private DotNetObjectReference? _dotNetRef;
private bool _showOverlay;
private bool _disposed;
-
+
private readonly string _fileUploadId = $"FileDropOverlay_{Guid.NewGuid()}";
protected override async Task OnInitializedAsync()
@@ -78,8 +79,11 @@ along with Foobar. If not, see
try
{
await _dialogManager.ShowLoadingDialogAsync();
+ var fileUploads = await _fileInputManager.CreateFileUploadsAsync(files, _fileUploadId);
_showOverlay = false;
- await _importManager.UploadFilesAsync(files, _fileUploadId);
+ await InvokeAsync(StateHasChanged);
+ await Task.Yield();
+ await _importManager.UploadFilesAsync(fileUploads);
await _jsRuntime.InvokeVoidAsync("globalFileDrag.reset", _dotNetRef);
}
finally
diff --git a/AudioCuesheetEditor/Shared/Inputs/TextField.razor b/AudioCuesheetEditor/Shared/Inputs/TextField.razor
index dfc5d589..fea7e524 100644
--- a/AudioCuesheetEditor/Shared/Inputs/TextField.razor
+++ b/AudioCuesheetEditor/Shared/Inputs/TextField.razor
@@ -44,9 +44,10 @@ along with Foobar. If not, see
async Task FileUploaded(InputFileChangeEventArgs e)
{
- if (_fileInputManager.IsValidForImportView(e.File))
+ var file = e.File;
+ if (_fileInputManager.IsValidForImportView(file.ContentType, file.Name))
{
- var fileContent = await _fileInputManager.ReadFileContentAsync(e.File);
+ var fileContent = await _fileInputManager.ReadFileContentAsync(file);
await TextChanged.InvokeAsync(fileContent);
}
}
From 6bcef35902dda9d578d6060adb80c6cc3ff9947c Mon Sep 17 00:00:00 2001
From: Sven <40752681+NeoCoderMatrix86@users.noreply.github.com>
Date: Mon, 9 Mar 2026 16:51:21 +0100
Subject: [PATCH 2/4] Update FileInputManagerTests.cs
---
.../Services/IO/FileInputManagerTests.cs | 69 ++++++++++---------
1 file changed, 36 insertions(+), 33 deletions(-)
diff --git a/AudioCuesheetEditor.Tests/Services/IO/FileInputManagerTests.cs b/AudioCuesheetEditor.Tests/Services/IO/FileInputManagerTests.cs
index f78b881c..e6d4bdce 100644
--- a/AudioCuesheetEditor.Tests/Services/IO/FileInputManagerTests.cs
+++ b/AudioCuesheetEditor.Tests/Services/IO/FileInputManagerTests.cs
@@ -15,7 +15,6 @@
//.
using AudioCuesheetEditor.Model.IO.Audio;
using AudioCuesheetEditor.Services.IO;
-using Microsoft.AspNetCore.Components.Forms;
using Microsoft.Extensions.Logging;
using Microsoft.JSInterop;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -34,11 +33,12 @@ public void CheckFileMimeType_ReturnsTrue_WhenContentTypeDoesNotMatchButExtensio
var jsRuntimeMock = new Mock();
var httpClientMock = new Mock();
var loggerMock = new Mock>();
- var file = CreateBrowserFile("test.mp3", "audio/wav");
+ var fileName = "test.mp3";
+ var contentType = "audio/wav";
var manager = new FileInputManager(jsRuntimeMock.Object, httpClientMock.Object, loggerMock.Object);
// Act
- var result = manager.CheckFileMimeType(file, "audio/mpeg", [".mp3"]);
+ var result = manager.CheckFileMimeType(contentType, fileName, "audio/mpeg", [".mp3"]);
// Assert
Assert.IsTrue(result);
@@ -51,11 +51,12 @@ public void CheckFileMimeType_ReturnsTrue_WhenContentTypeDoesMatchButNotExtensio
var jsRuntimeMock = new Mock();
var httpClientMock = new Mock();
var loggerMock = new Mock>();
- var file = CreateBrowserFile("test.mpeg", "audio/mpeg");
+ var fileName = "test.mpeg";
+ var contentType = "audio/mpeg";
var manager = new FileInputManager(jsRuntimeMock.Object, httpClientMock.Object, loggerMock.Object);
// Act
- var result = manager.CheckFileMimeType(file, "audio/mpeg", [".mp3", ".txt"]);
+ var result = manager.CheckFileMimeType(contentType, fileName, "audio/mpeg", [".mp3", ".txt"]);
// Assert
Assert.IsTrue(result);
@@ -68,11 +69,12 @@ public void CheckFileMimeType_ReturnsFalse_WhenExtensionDoesNotMatchAndContentTy
var jsRuntimeMock = new Mock();
var httpClientMock = new Mock();
var loggerMock = new Mock>();
- var file = CreateBrowserFile("test.flac", string.Empty);
+ var fileName = "test.flac";
+ var contentType = string.Empty;
var manager = new FileInputManager(jsRuntimeMock.Object, httpClientMock.Object, loggerMock.Object);
// Act
- var result = manager.CheckFileMimeType(file, "audio/flac", [".mp3"]);
+ var result = manager.CheckFileMimeType(contentType, fileName, "audio/flac", [".mp3"]);
// Assert
Assert.IsFalse(result);
@@ -85,11 +87,12 @@ public void CheckFileMimeType_ReturnsTrue_WhenContentTypeAndExtensionMatch()
var jsRuntimeMock = new Mock();
var httpClientMock = new Mock();
var loggerMock = new Mock>();
- var file = CreateBrowserFile("test.wav", "audio/wave");
+ var fileName = "test.wav";
+ var contentType = "audio/wave";
var manager = new FileInputManager(jsRuntimeMock.Object, httpClientMock.Object, loggerMock.Object);
// Act
- var result = manager.CheckFileMimeType(file, "audio/wave", [".wav"]);
+ var result = manager.CheckFileMimeType(contentType, fileName, "audio/wave", [".wav"]);
// Assert
Assert.IsTrue(result);
@@ -102,11 +105,12 @@ public void CheckFileMimeType_ReturnsTrue_WhenContentMainTypeMatch()
var jsRuntimeMock = new Mock();
var httpClientMock = new Mock();
var loggerMock = new Mock>();
- var file = CreateBrowserFile("history.txt", "text/plain");
+ var fileName = "history.txt";
+ var contentType = "text/plain";
var manager = new FileInputManager(jsRuntimeMock.Object, httpClientMock.Object, loggerMock.Object);
// Act
- var result = manager.CheckFileMimeType(file, "text/*", [".txt", ".text"]);
+ var result = manager.CheckFileMimeType(contentType, fileName, "text/*", [".txt", ".text"]);
// Assert
Assert.IsTrue(result);
@@ -119,11 +123,12 @@ public void IsValidAudiofile_ReturnsTrue_WithValidAudiocodec()
var jsRuntimeMock = new Mock();
var httpClientMock = new Mock();
var loggerMock = new Mock>();
- var file = CreateBrowserFile("test.wav", "audio/wav");
+ var fileName = "test.wav";
+ var contentType = "audio/wav";
var manager = new FileInputManager(jsRuntimeMock.Object, httpClientMock.Object, loggerMock.Object);
// Act
- var result = manager.IsValidAudiofile(file);
+ var result = manager.IsValidAudiofile(contentType, fileName);
// Assert
Assert.IsTrue(result);
@@ -136,11 +141,12 @@ public void IsValidAudiofile_ReturnsFalse_WithInvalidAudiocodecAndExtension()
var jsRuntimeMock = new Mock();
var httpClientMock = new Mock();
var loggerMock = new Mock>();
- var file = CreateBrowserFile("test.mock", "just a fantasy");
+ var fileName = "test.mock";
+ var contentType = "just a fantasy";
var manager = new FileInputManager(jsRuntimeMock.Object, httpClientMock.Object, loggerMock.Object);
// Act
- var result = manager.IsValidAudiofile(file);
+ var result = manager.IsValidAudiofile(contentType, fileName);
// Assert
Assert.IsFalse(result);
@@ -153,11 +159,12 @@ public void GetAudioCodec_ReturnsAudiocodec_WhenContentTypeMatches()
var jsRuntimeMock = new Mock();
var httpClientMock = new Mock();
var loggerMock = new Mock>();
- var file = CreateBrowserFile("test.wbem", "audio/webm");
+ var fileName = "test.wbem";
+ var contentType = "audio/webm";
var manager = new FileInputManager(jsRuntimeMock.Object, httpClientMock.Object, loggerMock.Object);
// Act
- var result = manager.GetAudioCodec(file);
+ var result = manager.GetAudioCodec(contentType, fileName);
// Assert
Assert.IsNotNull(result);
@@ -171,11 +178,12 @@ public void GetAudioCodec_ReturnsAudiocodec_WhenContentTypeAndFileExtensionMatch
var jsRuntimeMock = new Mock();
var httpClientMock = new Mock();
var loggerMock = new Mock>();
- var file = CreateBrowserFile("test.webm", "audio/webm");
+ var fileName = "test.wbem";
+ var contentType = "audio/webm";
var manager = new FileInputManager(jsRuntimeMock.Object, httpClientMock.Object, loggerMock.Object);
// Act
- var result = manager.GetAudioCodec(file);
+ var result = manager.GetAudioCodec(contentType, fileName);
// Assert
Assert.IsNotNull(result);
@@ -189,11 +197,12 @@ public void GetAudioCodec_ReturnsNull_WhenContentTypeAndFileExtensionNotMatch()
var jsRuntimeMock = new Mock();
var httpClientMock = new Mock();
var loggerMock = new Mock>();
- var file = CreateBrowserFile("test.acx", "fantasy stuff");
+ var fileName = "test.acx";
+ var contentType = "fantasy stuff";
var manager = new FileInputManager(jsRuntimeMock.Object, httpClientMock.Object, loggerMock.Object);
// Act
- var result = manager.GetAudioCodec(file);
+ var result = manager.GetAudioCodec(contentType, fileName);
// Assert
Assert.IsNull(result);
@@ -206,11 +215,12 @@ public void IsValidForImportView_ReturnsTrue_WhenFileIsHtml()
var jsRuntimeMock = new Mock();
var httpClientMock = new Mock();
var loggerMock = new Mock>();
- var file = CreateBrowserFile("test.html", "text/html");
+ var fileName = "test.html";
+ var contentType = "text/html";
var manager = new FileInputManager(jsRuntimeMock.Object, httpClientMock.Object, loggerMock.Object);
// Act
- var result = manager.IsValidForImportView(file);
+ var result = manager.IsValidForImportView(contentType, fileName);
// Assert
Assert.IsTrue(result);
@@ -223,22 +233,15 @@ public void IsValidForImportView_ReturnsFalse_WhenFileIsBinary()
var jsRuntimeMock = new Mock();
var httpClientMock = new Mock();
var loggerMock = new Mock>();
- var file = CreateBrowserFile("test.dat", "application/octet-stream");
+ var fileName = "test.dat";
+ var contentType = "application/octet-stream";
var manager = new FileInputManager(jsRuntimeMock.Object, httpClientMock.Object, loggerMock.Object);
// Act
- var result = manager.IsValidForImportView(file);
+ var result = manager.IsValidForImportView(contentType, fileName);
// Assert
Assert.IsFalse(result);
}
-
- private static IBrowserFile CreateBrowserFile(string name, string contentType)
- {
- var fileMock = new Mock();
- fileMock.Setup(f => f.Name).Returns(name);
- fileMock.Setup(f => f.ContentType).Returns(contentType);
- return fileMock.Object;
- }
}
}
\ No newline at end of file
From 47a52b590ed43c1c0a67fa79b239dd95f75d203d Mon Sep 17 00:00:00 2001
From: Sven <40752681+NeoCoderMatrix86@users.noreply.github.com>
Date: Mon, 9 Mar 2026 16:58:25 +0100
Subject: [PATCH 3/4] Update ImportManagerTests.cs
---
.../Services/IO/ImportManagerTests.cs | 51 ++++++++-----------
1 file changed, 21 insertions(+), 30 deletions(-)
diff --git a/AudioCuesheetEditor.Tests/Services/IO/ImportManagerTests.cs b/AudioCuesheetEditor.Tests/Services/IO/ImportManagerTests.cs
index a1481c15..5b6b2ec9 100644
--- a/AudioCuesheetEditor.Tests/Services/IO/ImportManagerTests.cs
+++ b/AudioCuesheetEditor.Tests/Services/IO/ImportManagerTests.cs
@@ -215,10 +215,10 @@ public async Task UploadFilesAsync_ProjectFile_ImportsCorrectly()
{
// Arrange
var fileContent = "This is the content";
- var file = CreateBrowserFileMock("test.projectfile", fileContent);
- _fileInputManagerMock.Setup(f => f.CheckFileMimeType(file, FileMimeTypes.Projectfile, It.IsAny>())).Returns(true);
- _fileInputManagerMock.Setup(f => f.CheckFileMimeType(file, FileMimeTypes.Cuesheet, It.IsAny>())).Returns(false);
- _fileInputManagerMock.Setup(f => f.IsValidForImportView(file)).Returns(false);
+ var file = new FileUpload("test.projectfile", "text/plain", fileContent);
+ _fileInputManagerMock.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Projectfile, It.IsAny>())).Returns(true);
+ _fileInputManagerMock.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Cuesheet, It.IsAny>())).Returns(false);
+ _fileInputManagerMock.Setup(f => f.IsValidForImportView(file.ContentType, file.Name)).Returns(false);
IImportfile? sessionStateContainerImportfile = null;
_sessionStateContainerMock.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x);
@@ -237,11 +237,11 @@ public async Task UploadFilesAsync_CuesheetFile_ImportsCorrectly()
{
// Arrange
var fileContent = "Cuesheet file content";
- var file = CreateBrowserFileMock("test.cue", fileContent);
-
- _fileInputManagerMock.Setup(f => f.CheckFileMimeType(file, FileMimeTypes.Projectfile, It.IsAny>())).Returns(false);
- _fileInputManagerMock.Setup(f => f.CheckFileMimeType(file, FileMimeTypes.Cuesheet, It.IsAny>())).Returns(true);
- _fileInputManagerMock.Setup(f => f.IsValidForImportView(file)).Returns(false);
+ var file = new FileUpload("test.cue", "text/plain", fileContent);
+
+ _fileInputManagerMock.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Projectfile, It.IsAny>())).Returns(false);
+ _fileInputManagerMock.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Cuesheet, It.IsAny>())).Returns(true);
+ _fileInputManagerMock.Setup(f => f.IsValidForImportView(file.ContentType, file.Name)).Returns(false);
IImportfile? sessionStateContainerImportfile = null;
_sessionStateContainerMock.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x);
@@ -260,11 +260,11 @@ public async Task UploadFilesAsync_TextFile_ImportsCorrectly()
{
// Arrange
var fileContent = "TextFileContent";
- var file = CreateBrowserFileMock("test.txt", fileContent);
-
- _fileInputManagerMock.Setup(f => f.CheckFileMimeType(file, FileMimeTypes.Projectfile, It.IsAny>())).Returns(false);
- _fileInputManagerMock.Setup(f => f.CheckFileMimeType(file, FileMimeTypes.Cuesheet, It.IsAny>())).Returns(false);
- _fileInputManagerMock.Setup(f => f.IsValidForImportView(file)).Returns(true);
+ var file = new FileUpload("test.txt", "text/plain", fileContent);
+
+ _fileInputManagerMock.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Projectfile, It.IsAny>())).Returns(false);
+ _fileInputManagerMock.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Cuesheet, It.IsAny>())).Returns(false);
+ _fileInputManagerMock.Setup(f => f.IsValidForImportView(file.ContentType, file.Name)).Returns(true);
IImportfile? sessionStateContainerImportfile = null;
_sessionStateContainerMock.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x);
@@ -282,13 +282,13 @@ public async Task UploadFilesAsync_TextFile_ImportsCorrectly()
public async Task UploadFilesAsync_WithAudiofile_ImportsCorrectly()
{
// Arrange
- var file = CreateBrowserFileMock("test.mp3");
-
- _fileInputManagerMock.Setup(f => f.CheckFileMimeType(file, FileMimeTypes.Projectfile, It.IsAny>())).Returns(false);
- _fileInputManagerMock.Setup(f => f.CheckFileMimeType(file, FileMimeTypes.Cuesheet, It.IsAny>())).Returns(false);
- _fileInputManagerMock.Setup(f => f.IsValidForImportView(file)).Returns(false);
- _fileInputManagerMock.Setup(f => f.IsValidAudiofile(file)).Returns(true);
- _fileInputManagerMock.Setup(f => f.CreateAudiofileAsync(It.IsAny(), It.IsAny(), It.IsAny>?>())).ReturnsAsync(new AudioCuesheetEditor.Model.IO.Audio.Audiofile(file.Name));
+ var file = new FileUpload("test.mp3", "audio/mpeg");
+
+ _fileInputManagerMock.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Projectfile, It.IsAny>())).Returns(false);
+ _fileInputManagerMock.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Cuesheet, It.IsAny>())).Returns(false);
+ _fileInputManagerMock.Setup(f => f.IsValidForImportView(file.ContentType, file.Name)).Returns(false);
+ _fileInputManagerMock.Setup(f => f.IsValidAudiofile(file.ContentType, file.Name)).Returns(true);
+ _fileInputManagerMock.Setup(f => f.CreateAudiofileAsync(It.IsAny(), It.IsAny>?>())).ReturnsAsync(new AudioCuesheetEditor.Model.IO.Audio.Audiofile(file.Name));
IImportfile? sessionStateContainerImportfile = null;
_sessionStateContainerMock.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x);
@@ -359,14 +359,5 @@ public void ImportData_ValidData_SetsImportfile()
Assert.AreEqual(importData, sessionStateContainerImportfile.FileContentRecognized);
Assert.AreEqual(ImportFileType.Textfile, sessionStateContainerImportfile.FileType);
}
-
- private static IBrowserFile CreateBrowserFileMock(string name, string content = "TestContent")
- {
- var fileMock = new Mock();
- fileMock.Setup(f => f.Name).Returns(name);
- fileMock.Setup(f => f.OpenReadStream(It.IsAny(), It.IsAny()))
- .Returns(new MemoryStream(Encoding.UTF8.GetBytes(content)));
- return fileMock.Object;
- }
}
}
\ No newline at end of file
From 8cbd6af3fc5e483dc37b01376de92892706c6e8b Mon Sep 17 00:00:00 2001
From: Sven <40752681+NeoCoderMatrix86@users.noreply.github.com>
Date: Tue, 10 Mar 2026 14:02:16 +0100
Subject: [PATCH 4/4] add tests
---
.../Services/IO/FileInputManagerTests.cs | 69 +++++++++++++++++++
.../Services/IO/FileInputManager.cs | 5 +-
2 files changed, 70 insertions(+), 4 deletions(-)
diff --git a/AudioCuesheetEditor.Tests/Services/IO/FileInputManagerTests.cs b/AudioCuesheetEditor.Tests/Services/IO/FileInputManagerTests.cs
index e6d4bdce..4e4de503 100644
--- a/AudioCuesheetEditor.Tests/Services/IO/FileInputManagerTests.cs
+++ b/AudioCuesheetEditor.Tests/Services/IO/FileInputManagerTests.cs
@@ -15,11 +15,18 @@
//.
using AudioCuesheetEditor.Model.IO.Audio;
using AudioCuesheetEditor.Services.IO;
+using Microsoft.AspNetCore.Components.Forms;
using Microsoft.Extensions.Logging;
using Microsoft.JSInterop;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
namespace AudioCuesheetEditor.Tests.Services.IO
{
@@ -243,5 +250,67 @@ public void IsValidForImportView_ReturnsFalse_WhenFileIsBinary()
// Assert
Assert.IsFalse(result);
}
+
+ [TestMethod]
+ public async Task CreateFileUploadsAsync_ReturnsFileUploads_WhenFileHasTextContentAsync()
+ {
+ // Arrange
+ var jsRuntimeMock = new Mock();
+ var httpClientMock = new Mock();
+ var loggerMock = new Mock>();
+ var manager = new FileInputManager(jsRuntimeMock.Object, httpClientMock.Object, loggerMock.Object);
+ var firstFile = CreateBrowserFile("Test.txt", "text/plain", "Just a test!");
+ var secondFile = CreateBrowserFile("Test.mp3", "audio/mpeg");
+ var fileInputId = nameof(CreateFileUploadsAsync_ReturnsFileUploads_WhenFileHasTextContentAsync);
+ IReadOnlyList browserfiles = [
+ firstFile,
+ secondFile
+ ];
+ var objectUrl = "Some object url!";
+ jsRuntimeMock.Setup(js => js.InvokeAsync(It.IsAny(), It.IsAny