From b784af0ea14136fd51611e4640f50300be98e29c Mon Sep 17 00:00:00 2001 From: NeoCodeMatrix86 <40752681+NeoCoderMatrix86@users.noreply.github.com> Date: Fri, 16 Oct 2026 11:21:08 +0200 Subject: [PATCH 1/2] set track end during import also --- .../Services/IO/ImportManagerTests.cs | 130 ++++++++++-------- .../Services/IO/ImportManager.cs | 6 + 2 files changed, 76 insertions(+), 60 deletions(-) diff --git a/AudioCuesheetEditor.Tests/Services/IO/ImportManagerTests.cs b/AudioCuesheetEditor.Tests/Services/IO/ImportManagerTests.cs index 0336850b..fabbd9fa 100644 --- a/AudioCuesheetEditor.Tests/Services/IO/ImportManagerTests.cs +++ b/AudioCuesheetEditor.Tests/Services/IO/ImportManagerTests.cs @@ -38,20 +38,29 @@ namespace AudioCuesheetEditor.Tests.Services.IO public class ImportManagerTests { private readonly ImportManager _service; - private readonly Mock _sessionStateContainerMock; - private readonly Mock _traceChangeManagerMock; - private readonly Mock _fileInputManagerMock; - private readonly Mock _textImportServiceMock; - private readonly Mock _trackManagerMock; + private readonly Mock _sessionStateContainer; + private readonly Mock _traceChangeManager; + private readonly Mock _fileInputManager; + private readonly Mock _textImportService; + private readonly Mock _trackManager; private readonly Mock _audioImportService; public ImportManagerTests() { - _traceChangeManagerMock = new(); - _sessionStateContainerMock = new(); - _fileInputManagerMock = new(); - _textImportServiceMock = new(); - _trackManagerMock = new(); - _trackManagerMock.Setup(x => x.CopyValues(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + _traceChangeManager = new(); + _sessionStateContainer = new(); + _fileInputManager = new(); + _textImportService = new(); + _trackManager = new(); + _trackManager.Setup(x => x.SetProperty(It.IsAny(), It.IsAny>>(), It.IsAny())) + .Callback((Track track, LambdaExpression propExpr, object value) => + { + var memberExpression = propExpr.Body as MemberExpression; + if (memberExpression?.Member is PropertyInfo propertyInfo) + { + propertyInfo.SetValue(track, value); + } + }); + _trackManager.Setup(x => x.CopyValues(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Callback((source, target, setIsLinkedToPreviousTrack, setPosition, setArtist, setTitle, setBegin, setEnd, setLength, setFlags, setPreGap, setPostGap) => { if (setIsLinkedToPreviousTrack) @@ -95,7 +104,7 @@ public ImportManagerTests() TrackManager_SetValue(target, x => x.PostGap, source.PostGap, false); } }); - _trackManagerMock.Setup(x => x.Clone(It.IsAny())).Returns(track => + _trackManager.Setup(x => x.Clone(It.IsAny())).Returns(track => { var clone = new Track(); Boolean setLength = true; @@ -103,12 +112,12 @@ public ImportManagerTests() { setLength = false; } - _trackManagerMock.Object.CopyValues(track, clone, setLength: setLength); + _trackManager.Object.CopyValues(track, clone, setLength: setLength); return clone; }); _audioImportService = new(); var loggerMock = new Mock>(); - _service = new ImportManager(_sessionStateContainerMock.Object, _traceChangeManagerMock.Object, _fileInputManagerMock.Object, _textImportServiceMock.Object, _trackManagerMock.Object, _audioImportService.Object, loggerMock.Object); + _service = new ImportManager(_sessionStateContainer.Object, _traceChangeManager.Object, _fileInputManager.Object, _textImportService.Object, _trackManager.Object, _audioImportService.Object, loggerMock.Object); } void TrackManager_SetValue(Track track, Expression> propertyExpression, TProperty value, Boolean signalTraceChangeManager = true) @@ -132,7 +141,7 @@ void TrackManager_SetValue(Track track, Expression x.AnalyseAsync(fileContent)).ReturnsAsync(importFile); - _sessionStateContainerMock.SetupGet(x => x.Importfile).Returns(importFile); + _textImportService.Setup(x => x.AnalyseAsync(fileContent)).ReturnsAsync(importFile); + _sessionStateContainer.SetupGet(x => x.Importfile).Returns(importFile); IList? sessionStateContainerImportAudiofiles = []; - _sessionStateContainerMock.SetupGet(x => x.ImportAudiofiles).Returns(() => sessionStateContainerImportAudiofiles); + _sessionStateContainer.SetupGet(x => x.ImportAudiofiles).Returns(() => sessionStateContainerImportAudiofiles); Cuesheet? sessionStateContainerImportCuesheet = null; - _sessionStateContainerMock.SetupSet(x => x.ImportCuesheet = It.IsAny()).Callback(cs => sessionStateContainerImportCuesheet = cs); - _sessionStateContainerMock.SetupGet(x => x.ImportCuesheet).Returns(() => sessionStateContainerImportCuesheet); + _sessionStateContainer.SetupSet(x => x.ImportCuesheet = It.IsAny()).Callback(cs => sessionStateContainerImportCuesheet = cs); + _sessionStateContainer.SetupGet(x => x.ImportCuesheet).Returns(() => sessionStateContainerImportCuesheet); IImportfile? sessionStateContainerImportfile = null; - _sessionStateContainerMock.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x); + _sessionStateContainer.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x); // Act await _service.AnalyseImportfile(); // Assert @@ -211,12 +220,12 @@ public async Task AnalyseImportfile_WithoutAnalysedCuesheet_DoesNothing() FileContent = fileContent, FileType = ImportFileType.Textfile, }; - _textImportServiceMock.Setup(x => x.AnalyseAsync(fileContent)).ReturnsAsync(importFile); - _sessionStateContainerMock.SetupGet(x => x.Importfile).Returns(importFile); + _textImportService.Setup(x => x.AnalyseAsync(fileContent)).ReturnsAsync(importFile); + _sessionStateContainer.SetupGet(x => x.Importfile).Returns(importFile); Cuesheet? sessionStateContainerImportCuesheet = null; - _sessionStateContainerMock.SetupSet(x => x.ImportCuesheet = It.IsAny()).Callback(cs => sessionStateContainerImportCuesheet = cs); + _sessionStateContainer.SetupSet(x => x.ImportCuesheet = It.IsAny()).Callback(cs => sessionStateContainerImportCuesheet = cs); IImportfile? sessionStateContainerImportfile = null; - _sessionStateContainerMock.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x); + _sessionStateContainer.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x); // Act await _service.AnalyseImportfile(); // Assert @@ -270,12 +279,12 @@ TRACK 08 AUDIO FileType = ImportFileType.Cuesheet }; IList? sessionStateContainerImportAudiofiles = []; - _sessionStateContainerMock.SetupGet(x => x.ImportAudiofiles).Returns(() => sessionStateContainerImportAudiofiles); - _sessionStateContainerMock.SetupGet(x => x.Importfile).Returns(() => sessionStateContainerImportFile); - _sessionStateContainerMock.SetupSet(x => x.Importfile = It.IsAny()).Callback(importfile => sessionStateContainerImportFile = importfile); + _sessionStateContainer.SetupGet(x => x.ImportAudiofiles).Returns(() => sessionStateContainerImportAudiofiles); + _sessionStateContainer.SetupGet(x => x.Importfile).Returns(() => sessionStateContainerImportFile); + _sessionStateContainer.SetupSet(x => x.Importfile = It.IsAny()).Callback(importfile => sessionStateContainerImportFile = importfile); Cuesheet? sessionStateContainerImportCuesheet = null; - _sessionStateContainerMock.SetupSet(x => x.ImportCuesheet = It.IsAny()).Callback(cuesheet => sessionStateContainerImportCuesheet = cuesheet); - _sessionStateContainerMock.SetupGet(x => x.ImportCuesheet).Returns(() => sessionStateContainerImportCuesheet); + _sessionStateContainer.SetupSet(x => x.ImportCuesheet = It.IsAny()).Callback(cuesheet => sessionStateContainerImportCuesheet = cuesheet); + _sessionStateContainer.SetupGet(x => x.ImportCuesheet).Returns(() => sessionStateContainerImportCuesheet); // Act await _service.AnalyseImportfile(); @@ -299,12 +308,12 @@ public async Task UploadFilesAsync_ProjectFile_ImportsCorrectly() // Arrange var fileContent = "This is the content"; 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); + _fileInputManager.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Projectfile, It.IsAny>())).Returns(true); + _fileInputManager.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Cuesheet, It.IsAny>())).Returns(false); + _fileInputManager.Setup(f => f.IsValidForImportView(file.ContentType, file.Name)).Returns(false); IImportfile? sessionStateContainerImportfile = null; - _sessionStateContainerMock.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x); + _sessionStateContainer.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x); // Act await _service.UploadFilesAsync([file]); @@ -322,12 +331,12 @@ public async Task UploadFilesAsync_CuesheetFile_ImportsCorrectly() var fileContent = "Cuesheet file content"; 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); + _fileInputManager.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Projectfile, It.IsAny>())).Returns(false); + _fileInputManager.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Cuesheet, It.IsAny>())).Returns(true); + _fileInputManager.Setup(f => f.IsValidForImportView(file.ContentType, file.Name)).Returns(false); IImportfile? sessionStateContainerImportfile = null; - _sessionStateContainerMock.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x); + _sessionStateContainer.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x); // Act await _service.UploadFilesAsync([file]); @@ -345,12 +354,12 @@ public async Task UploadFilesAsync_TextFile_ImportsCorrectly() var fileContent = "TextFileContent"; 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); + _fileInputManager.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Projectfile, It.IsAny>())).Returns(false); + _fileInputManager.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Cuesheet, It.IsAny>())).Returns(false); + _fileInputManager.Setup(f => f.IsValidForImportView(file.ContentType, file.Name)).Returns(true); IImportfile? sessionStateContainerImportfile = null; - _sessionStateContainerMock.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x); + _sessionStateContainer.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x); // Act await _service.UploadFilesAsync([file]); @@ -367,17 +376,17 @@ public async Task UploadFilesAsync_WithAudiofile_ImportsCorrectly() // Arrange 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.Name, file.ContentType)).Returns(true); - _fileInputManagerMock.Setup(f => f.CreateAudiofileAsync(It.IsAny())).ReturnsAsync(new Audiofile() { Name = file.Name }); + _fileInputManager.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Projectfile, It.IsAny>())).Returns(false); + _fileInputManager.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Cuesheet, It.IsAny>())).Returns(false); + _fileInputManager.Setup(f => f.IsValidForImportView(file.ContentType, file.Name)).Returns(false); + _fileInputManager.Setup(f => f.IsValidAudiofile(file.Name, file.ContentType)).Returns(true); + _fileInputManager.Setup(f => f.CreateAudiofileAsync(It.IsAny())).ReturnsAsync(new Audiofile() { Name = file.Name }); IImportfile? sessionStateContainerImportfile = null; - _sessionStateContainerMock.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x); + _sessionStateContainer.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x); IList? sessionStateContainerImportAudiofiles = []; - _sessionStateContainerMock.SetupGet(x => x.ImportAudiofiles).Returns(() => sessionStateContainerImportAudiofiles); - _sessionStateContainerMock.SetupSet(x => x.ImportAudiofiles = It.IsAny>()).Callback>(x => sessionStateContainerImportAudiofiles = x); + _sessionStateContainer.SetupGet(x => x.ImportAudiofiles).Returns(() => sessionStateContainerImportAudiofiles); + _sessionStateContainer.SetupSet(x => x.ImportAudiofiles = It.IsAny>()).Callback>(x => sessionStateContainerImportAudiofiles = x); // Act await _service.UploadFilesAsync([file]); @@ -400,8 +409,8 @@ public async Task ImportCuesheetAsync_WithImportCuesheetAvailable_ImportsCueshee { Artist = "Track Artist 2", Title = "Track Title 2", - End = new TimeSpan(0, 8, 54), }; + var audiofileDuration = new TimeSpan(0, 12, 45); var sessionStateContainerImportCuesheet = new Cuesheet() { Artist = "Artist 123", @@ -411,7 +420,8 @@ public async Task ImportCuesheetAsync_WithImportCuesheetAvailable_ImportsCueshee { Name = "song.mp3", ObjectURL = "Just a test", - Tracks = [track1, track2] + Tracks = [track1, track2], + Duration = audiofileDuration } ] }; @@ -419,13 +429,13 @@ public async Task ImportCuesheetAsync_WithImportCuesheetAvailable_ImportsCueshee track2.Cuesheet = sessionStateContainerImportCuesheet; track1.Audiofile = sessionStateContainerImportCuesheet.Audiofiles.First(); track2.Audiofile = sessionStateContainerImportCuesheet.Audiofiles.First(); - _sessionStateContainerMock.SetupGet(x => x.ImportCuesheet).Returns(sessionStateContainerImportCuesheet); - _sessionStateContainerMock.SetupSet(x => x.ImportCuesheet = It.IsAny()).Callback(cuesheet => sessionStateContainerImportCuesheet = cuesheet); + _sessionStateContainer.SetupGet(x => x.ImportCuesheet).Returns(sessionStateContainerImportCuesheet); + _sessionStateContainer.SetupSet(x => x.ImportCuesheet = It.IsAny()).Callback(cuesheet => sessionStateContainerImportCuesheet = cuesheet); Cuesheet sessionStateContainerCuesheet = new(); - _sessionStateContainerMock.SetupSet(x => x.Cuesheet = It.IsAny()).Callback(cuesheet => sessionStateContainerCuesheet = cuesheet); - _sessionStateContainerMock.SetupGet(x => x.Cuesheet).Returns(() => sessionStateContainerCuesheet); + _sessionStateContainer.SetupSet(x => x.Cuesheet = It.IsAny()).Callback(cuesheet => sessionStateContainerCuesheet = cuesheet); + _sessionStateContainer.SetupGet(x => x.Cuesheet).Returns(() => sessionStateContainerCuesheet); IList? sessionStateContainerImportAudiofiles = []; - _sessionStateContainerMock.SetupGet(x => x.ImportAudiofiles).Returns(() => sessionStateContainerImportAudiofiles); + _sessionStateContainer.SetupGet(x => x.ImportAudiofiles).Returns(() => sessionStateContainerImportAudiofiles); // Act await _service.ImportCuesheetAsync(); // Assert @@ -440,8 +450,8 @@ public async Task ImportCuesheetAsync_WithImportCuesheetAvailable_ImportsCueshee Assert.AreEqual(track2.Artist, sessionStateContainerCuesheet.Audiofiles.First().Tracks.Last().Artist); Assert.AreEqual(track2.Title, sessionStateContainerCuesheet.Audiofiles.First().Tracks.Last().Title); Assert.AreEqual(track1.End, sessionStateContainerCuesheet.Audiofiles.First().Tracks.Last().Begin); - Assert.AreEqual(track2.End, sessionStateContainerCuesheet.Audiofiles.First().Tracks.Last().End); - _traceChangeManagerMock.Verify(x => x.RemoveTracedChanges(It.IsAny>())); + Assert.AreEqual(audiofileDuration, sessionStateContainerCuesheet.Audiofiles.First().Tracks.Last().End); + _traceChangeManager.Verify(x => x.RemoveTracedChanges(It.IsAny>())); } [TestMethod] @@ -450,7 +460,7 @@ public void ImportData_ValidData_SetsImportfile() // Arrange var importData = nameof(ImportData_ValidData_SetsImportfile); IImportfile? sessionStateContainerImportfile = null; - _sessionStateContainerMock.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x); + _sessionStateContainer.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x); // Act _service.ImportData(importData); // Assert diff --git a/AudioCuesheetEditor/Services/IO/ImportManager.cs b/AudioCuesheetEditor/Services/IO/ImportManager.cs index e82f031c..8294d69c 100644 --- a/AudioCuesheetEditor/Services/IO/ImportManager.cs +++ b/AudioCuesheetEditor/Services/IO/ImportManager.cs @@ -299,6 +299,12 @@ void AttachClonedAudiofiles(Cuesheet target, IEnumerable audiofiles) position++; targetAudiofile.Tracks.Add(clone); } + //Set last track end + var lastTrack = targetAudiofile.Tracks.LastOrDefault(); + if ((lastTrack?.End.HasValue == false) && (targetAudiofile.Duration.HasValue == true)) + { + _trackManager.SetProperty(lastTrack, x => x.End, targetAudiofile.Duration); + } target.Audiofiles.Add(targetAudiofile); } } From 44b81192ed060b35744cdc080a5d1fbd7ba411db Mon Sep 17 00:00:00 2001 From: NeoCodeMatrix86 <40752681+NeoCoderMatrix86@users.noreply.github.com> Date: Fri, 16 Oct 2026 11:23:03 +0200 Subject: [PATCH 2/2] update libraries --- .../AudioCuesheetEditor.End2EndTests.csproj | 2 +- .../AudioCuesheetEditor.Tests.csproj | 6 +++--- AudioCuesheetEditor/AudioCuesheetEditor.csproj | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/AudioCuesheetEditor.End2EndTests/AudioCuesheetEditor.End2EndTests.csproj b/AudioCuesheetEditor.End2EndTests/AudioCuesheetEditor.End2EndTests.csproj index 6b8d48c1..d02d940a 100644 --- a/AudioCuesheetEditor.End2EndTests/AudioCuesheetEditor.End2EndTests.csproj +++ b/AudioCuesheetEditor.End2EndTests/AudioCuesheetEditor.End2EndTests.csproj @@ -25,7 +25,7 @@ - + diff --git a/AudioCuesheetEditor.Tests/AudioCuesheetEditor.Tests.csproj b/AudioCuesheetEditor.Tests/AudioCuesheetEditor.Tests.csproj index 0714cf11..8fec56a1 100644 --- a/AudioCuesheetEditor.Tests/AudioCuesheetEditor.Tests.csproj +++ b/AudioCuesheetEditor.Tests/AudioCuesheetEditor.Tests.csproj @@ -19,12 +19,12 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/AudioCuesheetEditor/AudioCuesheetEditor.csproj b/AudioCuesheetEditor/AudioCuesheetEditor.csproj index 757d9745..8c641a64 100644 --- a/AudioCuesheetEditor/AudioCuesheetEditor.csproj +++ b/AudioCuesheetEditor/AudioCuesheetEditor.csproj @@ -30,13 +30,13 @@ - - + + - - - - + + + +