From 6ab71c4f9adefe8d99891faa3647e3ee355e3eb5 Mon Sep 17 00:00:00 2001 From: darthsharp <48331467+darthsharp@users.noreply.github.com> Date: Fri, 24 Apr 2026 13:05:46 +0200 Subject: [PATCH] Replace `Progress` with `SynchronousProgress` for consistent synchronous handling of progress updates in `BrewImportCommand` and related tests. Added `SynchronousProgress` implementation. --- .../SynchronousProgress.cs | 17 +++++++++++++++++ .../HomeBrew/Import/BrewImportCommand.cs | 4 ++-- .../Import/BrewImporterTests.cs | 9 +++------ 3 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 source/CreativeCoders.MacOS.HomeBrew/SynchronousProgress.cs diff --git a/source/CreativeCoders.MacOS.HomeBrew/SynchronousProgress.cs b/source/CreativeCoders.MacOS.HomeBrew/SynchronousProgress.cs new file mode 100644 index 0000000..aab1db2 --- /dev/null +++ b/source/CreativeCoders.MacOS.HomeBrew/SynchronousProgress.cs @@ -0,0 +1,17 @@ +using CreativeCoders.Core; + +namespace CreativeCoders.MacOS.HomeBrew; + +/// +/// An implementation that invokes the callback synchronously on the +/// calling thread. Unlike , which posts to the captured +/// (or the when none exists), +/// this class guarantees that the handler runs inline before returns. +/// +public sealed class SynchronousProgress(Action handler) : IProgress +{ + private readonly Action _handler = Ensure.NotNull(handler); + + /// + public void Report(T value) => _handler(value); +} diff --git a/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/Import/BrewImportCommand.cs b/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/Import/BrewImportCommand.cs index c39d83d..c2024be 100644 --- a/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/Import/BrewImportCommand.cs +++ b/source/CreativeCoders.MacSynkker.Cli/Commands/HomeBrew/Import/BrewImportCommand.cs @@ -1,7 +1,7 @@ using CreativeCoders.Cli.Core; using CreativeCoders.Core; +using CreativeCoders.MacOS.HomeBrew; using CreativeCoders.MacOS.HomeBrew.Import; -using CreativeCoders.SysConsole.Core; using JetBrains.Annotations; using Spectre.Console; @@ -29,7 +29,7 @@ public async Task ExecuteAsync(BrewImportOptions options) _ansiConsole.MarkupLine($"Importing Homebrew software from '{options.InputPath}'"); _ansiConsole.WriteLine(); - var progress = new Progress(OnProgress); + var progress = new SynchronousProgress(OnProgress); try { diff --git a/tests/CreativeCoders.MacOS.HomeBrew.Tests/Import/BrewImporterTests.cs b/tests/CreativeCoders.MacOS.HomeBrew.Tests/Import/BrewImporterTests.cs index d35c276..fcfd659 100644 --- a/tests/CreativeCoders.MacOS.HomeBrew.Tests/Import/BrewImporterTests.cs +++ b/tests/CreativeCoders.MacOS.HomeBrew.Tests/Import/BrewImporterTests.cs @@ -1,5 +1,6 @@ using System.Text.Json; using AwesomeAssertions; +using CreativeCoders.MacOS.HomeBrew; using CreativeCoders.MacOS.HomeBrew.Import; using CreativeCoders.MacOS.HomeBrew.Models.Export; using FakeItEasy; @@ -130,14 +131,11 @@ public async Task ImportAsync_ReportsProgressForEachStep() Casks = [new BrewExportCaskModel { Token = "firefox" }] }; var reports = new List(); - var progress = new Progress(reports.Add); + var progress = new SynchronousProgress(reports.Add); // Act await sut.ImportAsync(exportModel, progress); - // Allow the Progress SynchronizationContext to flush callbacks - await Task.Delay(50); - // Assert reports.Should().Contain(r => r.Step == BrewImportStep.Tap && r.State == BrewImportStepState.Starting && r.Target == "some/tap"); @@ -162,13 +160,12 @@ public async Task ImportAsync_WhenStepFails_ReportsFailedProgressWithError() Formulae = [new BrewExportFormulaModel { Name = "bad" }] }; var reports = new List(); - var progress = new Progress(reports.Add); + var progress = new SynchronousProgress(reports.Add); // Act var act = () => sut.ImportAsync(exportModel, progress); await act.Should().ThrowAsync(); - await Task.Delay(50); // Assert reports.Should().Contain(r => r.State == BrewImportStepState.Failed