diff --git a/src/Stack.Tests/Commands/Branch/AddBranchCommandHandlerTests.cs b/src/Stack.Tests/Commands/Branch/AddBranchCommandHandlerTests.cs index 4e3a6207..dc8f8d91 100644 --- a/src/Stack.Tests/Commands/Branch/AddBranchCommandHandlerTests.cs +++ b/src/Stack.Tests/Commands/Branch/AddBranchCommandHandlerTests.cs @@ -6,10 +6,11 @@ using Stack.Git; using Stack.Infrastructure; using Stack.Tests.Helpers; +using Xunit.Abstractions; namespace Stack.Tests.Commands.Branch; -public class AddBranchCommandHandlerTests +public class AddBranchCommandHandlerTests(ITestOutputHelper testOutputHelper) { [Fact] public async Task WhenNoInputsProvided_AsksForStackAndBranchAndConfirms_AddsBranchToStack() @@ -33,7 +34,7 @@ public async Task WhenNoInputsProvided_AsksForStackAndBranchAndConfirms_AddsBran .WithStack(stack => stack.WithName("Stack2").WithRemoteUri(repo.RemoteUri).WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new AddBranchCommandHandler(inputProvider, logger, gitClient, stackConfig); @@ -73,13 +74,10 @@ public async Task WhenStackNameProvided_DoesNotAskForStackName_AddsBranchFromSta .WithStack(stack => stack.WithName("Stack2").WithRemoteUri(repo.RemoteUri).WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new AddBranchCommandHandler(inputProvider, logger, gitClient, stackConfig); - - - inputProvider.Select(Questions.SelectBranch, Arg.Any()).Returns(branchToAdd); // Act @@ -115,11 +113,10 @@ public async Task WhenOnlyOneStackExists_DoesNotAskForStackName_AddsBranchFromSt .WithBranch(branch => branch.WithName(anotherBranch))) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new AddBranchCommandHandler(inputProvider, logger, gitClient, stackConfig); - inputProvider.Select(Questions.SelectBranch, Arg.Any()).Returns(branchToAdd); // Act @@ -155,12 +152,10 @@ public async Task WhenStackNameProvided_ButStackDoesNotExist_Throws() .WithStack(stack => stack.WithName("Stack2").WithRemoteUri(repo.RemoteUri).WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new AddBranchCommandHandler(inputProvider, logger, gitClient, stackConfig); - - // Act and assert var invalidStackName = Some.Name(); await handler.Invoking(async h => await h.Handle(new AddBranchCommandInputs(invalidStackName, null))) @@ -191,12 +186,10 @@ public async Task WhenBranchNameProvided_DoesNotAskForBranchName_AddsBranchFromS .WithStack(stack => stack.WithName("Stack2").WithRemoteUri(repo.RemoteUri).WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new AddBranchCommandHandler(inputProvider, logger, gitClient, stackConfig); - - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); // Act @@ -233,12 +226,10 @@ public async Task WhenBranchNameProvided_ButBranchDoesNotExistLocally_Throws() .WithStack(stack => stack.WithName("Stack2").WithRemoteUri(repo.RemoteUri).WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new AddBranchCommandHandler(inputProvider, logger, gitClient, stackConfig); - - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); // Act and assert @@ -273,12 +264,10 @@ public async Task WhenBranchNameProvided_ButBranchAlreadyExistsInStack_Throws() .WithStack(stack => stack.WithName("Stack2").WithRemoteUri(repo.RemoteUri).WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new AddBranchCommandHandler(inputProvider, logger, gitClient, stackConfig); - - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); // Act and assert @@ -310,12 +299,10 @@ public async Task WhenAllInputsProvided_DoesNotAskForAnything_AddsBranchFromStac .WithStack(stack => stack.WithName("Stack2").WithRemoteUri(repo.RemoteUri).WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new AddBranchCommandHandler(inputProvider, logger, gitClient, stackConfig); - - // Act await handler.Handle(new AddBranchCommandInputs("Stack1", branchToAdd)); diff --git a/src/Stack.Tests/Commands/Branch/NewBranchCommandHandlerTests.cs b/src/Stack.Tests/Commands/Branch/NewBranchCommandHandlerTests.cs index f36b6749..fabc9bd3 100644 --- a/src/Stack.Tests/Commands/Branch/NewBranchCommandHandlerTests.cs +++ b/src/Stack.Tests/Commands/Branch/NewBranchCommandHandlerTests.cs @@ -6,10 +6,11 @@ using Stack.Git; using Stack.Infrastructure; using Stack.Tests.Helpers; +using Xunit.Abstractions; namespace Stack.Tests.Commands.Branch; -public class NewBranchCommandHandlerTests +public class NewBranchCommandHandlerTests(ITestOutputHelper testOutputHelper) { [Fact] public async Task WhenNoInputsProvided_AsksForStackAndBranch_CreatesAndAddsBranchToStack_PushesToRemote_AndSwitchesToBranch() @@ -24,7 +25,7 @@ public async Task WhenNoInputsProvided_AsksForStackAndBranch_CreatesAndAddsBranc .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var stackConfig = new TestStackConfigBuilder() .WithStack(stack => stack @@ -68,7 +69,7 @@ public async Task WhenStackNameProvided_DoesNotAskForStackName_CreatesAndAddsBra .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var stackConfig = new TestStackConfigBuilder() .WithStack(stack => stack @@ -110,7 +111,7 @@ public async Task WhenOnlyOneStackExists_DoesNotAskForStackName_CreatesAndAddsBr .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var stackConfig = new TestStackConfigBuilder() .WithStack(stack => stack @@ -147,7 +148,7 @@ public async Task WhenStackNameProvided_ButStackDoesNotExist_Throws() .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var stackConfig = new TestStackConfigBuilder() .WithStack(stack => stack @@ -183,7 +184,7 @@ public async Task WhenBranchNameProvided_DoesNotAskForBranchName_CreatesAndAddsB .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var stackConfig = new TestStackConfigBuilder() .WithStack(stack => stack @@ -224,7 +225,7 @@ public async Task WhenBranchNameProvided_ButBranchAlreadyExistLocally_Throws() .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var stackConfig = new TestStackConfigBuilder() .WithStack(stack => stack @@ -261,7 +262,7 @@ public async Task WhenBranchNameProvided_ButBranchAlreadyExistsInStack_Throws() .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var stackConfig = new TestStackConfigBuilder() .WithStack(stack => stack @@ -299,7 +300,7 @@ public async Task WhenStackHasANameWithMultipleWords_SuggestsAGoodDefaultNewBran .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var stackConfig = new TestStackConfigBuilder() .WithStack(stack => stack @@ -342,7 +343,7 @@ public async Task WhenPushToTheRemoteFails_StillCreatesTheBranchLocallyAndAddsIt .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = Substitute.ForPartsOf(logger, repo.GitClientSettings); var stackConfig = new TestStackConfigBuilder() .WithStack(stack => stack diff --git a/src/Stack.Tests/Commands/Branch/RemoveBranchCommandHandlerTests.cs b/src/Stack.Tests/Commands/Branch/RemoveBranchCommandHandlerTests.cs index ae148f84..b41de55b 100644 --- a/src/Stack.Tests/Commands/Branch/RemoveBranchCommandHandlerTests.cs +++ b/src/Stack.Tests/Commands/Branch/RemoveBranchCommandHandlerTests.cs @@ -6,10 +6,11 @@ using Stack.Git; using Stack.Infrastructure; using Stack.Tests.Helpers; +using Xunit.Abstractions; namespace Stack.Tests.Commands.Branch; -public class RemoveBranchCommandHandlerTests +public class RemoveBranchCommandHandlerTests(ITestOutputHelper testOutputHelper) { [Fact] public async Task WhenNoInputsProvided_AsksForStackAndBranchAndConfirms_RemovesBranchFromStack() @@ -34,7 +35,7 @@ public async Task WhenNoInputsProvided_AsksForStackAndBranchAndConfirms_RemovesB .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClient, stackConfig); @@ -76,12 +77,10 @@ public async Task WhenStackNameProvided_DoesNotAskForStackName_RemovesBranchFrom .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClient, stackConfig); - - inputProvider.Select(Questions.SelectBranch, Arg.Any()).Returns(branchToRemove); inputProvider.Confirm(Questions.ConfirmRemoveBranch).Returns(true); @@ -120,11 +119,10 @@ public async Task WhenStackNameProvided_ButStackDoesNotExist_Throws() .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClient, stackConfig); - // Act and assert var invalidStackName = Some.Name(); await handler.Invoking(async h => await h.Handle(new RemoveBranchCommandInputs(invalidStackName, null, false))) @@ -156,12 +154,10 @@ public async Task WhenBranchNameProvided_DoesNotAskForBranchName_RemovesBranchFr .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClient, stackConfig); - - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); inputProvider.Confirm(Questions.ConfirmRemoveBranch).Returns(true); @@ -200,12 +196,10 @@ public async Task WhenBranchNameProvided_ButBranchDoesNotExistInStack_Throws() .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClient, stackConfig); - - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); // Act and assert @@ -235,12 +229,10 @@ public async Task WhenOnlyOneStackExists_DoesNotAskForStackName() .WithBranch(b => b.WithName(branchToRemove))) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClient, stackConfig); - - inputProvider.Select(Questions.SelectBranch, Arg.Any()).Returns(branchToRemove); inputProvider.Confirm(Questions.ConfirmRemoveBranch).Returns(true); @@ -279,12 +271,10 @@ public async Task WhenConfirmProvided_DoesNotAskForConfirmation_RemovesBranchFro .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new RemoveBranchCommandHandler(inputProvider, logger, gitClient, stackConfig); - - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); inputProvider.Select(Questions.SelectBranch, Arg.Any()).Returns(branchToRemove); diff --git a/src/Stack.Tests/Commands/Helpers/StackHelpersTests.cs b/src/Stack.Tests/Commands/Helpers/StackHelpersTests.cs index 7832bbff..1298711b 100644 --- a/src/Stack.Tests/Commands/Helpers/StackHelpersTests.cs +++ b/src/Stack.Tests/Commands/Helpers/StackHelpersTests.cs @@ -28,9 +28,13 @@ public void UpdateStack_WhenThereAreConflictsMergingBranches_AndUpdateIsContinue sourceBranch, [new Config.Branch(branch1, []), new Config.Branch(branch2, [])] ); - var branchDetail1 = new BranchDetail(branch1, true, new Commit(Some.Sha(), Some.Name()), new RemoteTrackingBranchStatus($"origin/{branch1}", true, 0, 0), null, null); - var branchDetail2 = new BranchDetail(branch2, true, new Commit(Some.Sha(), Some.Name()), new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), null, null); - var stackStatus = new StackStatus("Stack1", new BranchDetailBase(sourceBranch, true, null, null), [branchDetail1, branchDetail2]); + var branchDetail1 = new BranchDetail( + branch1, true, new Commit(Some.Sha(), Some.Name()), + new RemoteTrackingBranchStatus($"origin/{branch1}", true, 0, 0), null, null, + [new BranchDetail( + branch2, true, new Commit(Some.Sha(), Some.Name()), + new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), null, null, [])]); + var stackStatus = new StackStatus("Stack1", new SourceBranchDetail(sourceBranch, true, null, null), [branchDetail1]); inputProvider .Select( @@ -76,9 +80,9 @@ public void UpdateStack_WhenThereAreConflictsMergingBranches_AndUpdateIsAborted_ sourceBranch, [new Config.Branch(branch1, []), new Config.Branch(branch2, [])] ); - var branchDetail1 = new BranchDetail(branch1, true, new Commit(Some.Sha(), Some.Name()), new RemoteTrackingBranchStatus($"origin/{branch1}", true, 0, 0), null, null); - var branchDetail2 = new BranchDetail(branch2, true, new Commit(Some.Sha(), Some.Name()), new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), null, null); - var stackStatus = new StackStatus("Stack1", new BranchDetailBase(sourceBranch, true, null, null), [branchDetail1, branchDetail2]); + var branchDetail1 = new BranchDetail(branch1, true, new Commit(Some.Sha(), Some.Name()), new RemoteTrackingBranchStatus($"origin/{branch1}", true, 0, 0), null, null, []); + var branchDetail2 = new BranchDetail(branch2, true, new Commit(Some.Sha(), Some.Name()), new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), null, null, []); + var stackStatus = new StackStatus("Stack1", new SourceBranchDetail(sourceBranch, true, null, null), [branchDetail1, branchDetail2]); gitClient .When(g => g.MergeFromLocalSourceBranch(sourceBranch)) diff --git a/src/Stack.Tests/Commands/PullRequests/OpenPullRequestsCommandHandlerTests.cs b/src/Stack.Tests/Commands/PullRequests/OpenPullRequestsCommandHandlerTests.cs index 2781e8b1..c7c4bf11 100644 --- a/src/Stack.Tests/Commands/PullRequests/OpenPullRequestsCommandHandlerTests.cs +++ b/src/Stack.Tests/Commands/PullRequests/OpenPullRequestsCommandHandlerTests.cs @@ -6,10 +6,11 @@ using Stack.Git; using Stack.Infrastructure; using Stack.Tests.Helpers; +using Xunit.Abstractions; namespace Stack.Tests.Commands.PullRequests; -public class OpenPullRequestsCommandHandlerTests +public class OpenPullRequestsCommandHandlerTests(ITestOutputHelper testOutputHelper) { [Fact] public async Task WhenThereAreMultiplePullRequestsInAStack_OpensAllPullRequests() @@ -38,12 +39,11 @@ public async Task WhenThereAreMultiplePullRequestsInAStack_OpensAllPullRequests( .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var fileOperations = Substitute.For(); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new OpenPullRequestsCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); var prForBranch1 = new GitHubPullRequest(1, "PR Title", string.Empty, GitHubPullRequestStates.Open, Some.HttpsUri(), false); @@ -91,12 +91,11 @@ public async Task WhenThereAreSomePullRequestsInAStack_OpensAllPullRequests() .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var fileOperations = Substitute.For(); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new OpenPullRequestsCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); var prForBranch1 = new GitHubPullRequest(1, "PR Title", string.Empty, GitHubPullRequestStates.Open, Some.HttpsUri(), false); @@ -141,12 +140,11 @@ public async Task WhenStackNameIsProvided_OpensAllPullRequestsForTheStack() .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var fileOperations = Substitute.For(); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new OpenPullRequestsCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - var prForBranch1 = new GitHubPullRequest(1, "PR Title", string.Empty, GitHubPullRequestStates.Open, Some.HttpsUri(), false); gitHubClient .GetPullRequest(branch1) @@ -188,12 +186,11 @@ public async Task WhenOnlyOneStackExists_DoesNotAskForStackName_OpensAllPullRequ .WithBranch(branch => branch.WithName(branch2))) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var fileOperations = Substitute.For(); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new OpenPullRequestsCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - var prForBranch1 = new GitHubPullRequest(1, "PR Title", string.Empty, GitHubPullRequestStates.Open, Some.HttpsUri(), false); gitHubClient .GetPullRequest(branch1) @@ -239,12 +236,11 @@ public async Task WhenStackNameIsProvided_ButItStackDoesNotExist_Throws() .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var fileOperations = Substitute.For(); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new OpenPullRequestsCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - // Act and assert var invalidStackName = Some.Name(); await handler.Invoking(h => h.Handle(new OpenPullRequestsCommandInputs(invalidStackName))) diff --git a/src/Stack.Tests/Commands/Remote/SyncStackCommandHandlerTests.cs b/src/Stack.Tests/Commands/Remote/SyncStackCommandHandlerTests.cs index 9e2a4fe5..c4032365 100644 --- a/src/Stack.Tests/Commands/Remote/SyncStackCommandHandlerTests.cs +++ b/src/Stack.Tests/Commands/Remote/SyncStackCommandHandlerTests.cs @@ -49,7 +49,6 @@ public async Task WhenChangesExistOnTheSourceBranchOnTheRemote_PullsChanges_Upda gitClient.ChangeBranch(branch1); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); inputProvider.Confirm(Questions.ConfirmSyncStack).Returns(true); @@ -98,7 +97,6 @@ public async Task WhenNameIsProvided_DoesNotAskForName_SyncsCorrectStack() gitClient.ChangeBranch(branch1); - inputProvider.Confirm(Questions.ConfirmSyncStack).Returns(true); // Act @@ -147,7 +145,6 @@ public async Task WhenNameIsProvided_ButStackDoesNotExist_Throws() gitClient.ChangeBranch(branch1); - // Act and assert var invalidStackName = Some.Name(); await handler.Invoking(async h => await h.Handle(new SyncStackCommandInputs(invalidStackName, 5, false, false, false))) @@ -193,7 +190,6 @@ public async Task WhenOnASpecificBranchInTheStack_TheSameBranchIsSetAsCurrentAft // We are on a specific branch in the stack gitClient.ChangeBranch(branch1); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); inputProvider.Confirm(Questions.ConfirmSyncStack).Returns(true); @@ -239,7 +235,6 @@ public async Task WhenOnlyASingleStackExists_DoesNotAskForStackName_SyncsStack() gitClient.ChangeBranch(branch1); - inputProvider.Confirm(Questions.ConfirmSyncStack).Returns(true); // Act @@ -277,8 +272,7 @@ public async Task WhenUsingRebase_ChangesExistOnTheSourceBranchOnTheRemote_Pulls .WithName("Stack1") .WithRemoteUri(repo.RemoteUri) .WithSourceBranch(sourceBranch) - .WithBranch(stackBranch => stackBranch.WithName(branch1)) - .WithBranch(stackBranch => stackBranch.WithName(branch2))) + .WithBranch(stackBranch => stackBranch.WithName(branch1).WithChildBranch(b => b.WithName(branch2)))) .WithStack(stack => stack .WithName("Stack2") .WithRemoteUri(repo.RemoteUri) @@ -292,7 +286,6 @@ public async Task WhenUsingRebase_ChangesExistOnTheSourceBranchOnTheRemote_Pulls gitClient.ChangeBranch(branch1); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); inputProvider.Confirm(Questions.ConfirmSyncStack).Returns(true); @@ -331,8 +324,7 @@ public async Task WhenUsingMerge_ChangesExistOnTheSourceBranchOnTheRemote_PullsC .WithName("Stack1") .WithRemoteUri(repo.RemoteUri) .WithSourceBranch(sourceBranch) - .WithBranch(stackBranch => stackBranch.WithName(branch1)) - .WithBranch(stackBranch => stackBranch.WithName(branch2))) + .WithBranch(stackBranch => stackBranch.WithName(branch1).WithChildBranch(b => b.WithName(branch2)))) .WithStack(stack => stack .WithName("Stack2") .WithRemoteUri(repo.RemoteUri) @@ -346,7 +338,6 @@ public async Task WhenUsingMerge_ChangesExistOnTheSourceBranchOnTheRemote_PullsC gitClient.ChangeBranch(branch1); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); inputProvider.Confirm(Questions.ConfirmSyncStack).Returns(true); @@ -386,8 +377,7 @@ public async Task WhenNotSpecifyingRebaseOrMerge_AndUpdateSettingIsRebase_DoesSy .WithName("Stack1") .WithRemoteUri(repo.RemoteUri) .WithSourceBranch(sourceBranch) - .WithBranch(stackBranch => stackBranch.WithName(branch1)) - .WithBranch(stackBranch => stackBranch.WithName(branch2))) + .WithBranch(stackBranch => stackBranch.WithName(branch1).WithChildBranch(b => b.WithName(branch2)))) .WithStack(stack => stack .WithName("Stack2") .WithRemoteUri(repo.RemoteUri) @@ -401,7 +391,6 @@ public async Task WhenNotSpecifyingRebaseOrMerge_AndUpdateSettingIsRebase_DoesSy gitClient.ChangeBranch(branch1); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); inputProvider.Confirm(Questions.ConfirmSyncStack).Returns(true); @@ -441,8 +430,7 @@ public async Task WhenNotSpecifyingRebaseOrMerge_AndUpdateSettingIsMerge_DoesSyn .WithName("Stack1") .WithRemoteUri(repo.RemoteUri) .WithSourceBranch(sourceBranch) - .WithBranch(stackBranch => stackBranch.WithName(branch1)) - .WithBranch(stackBranch => stackBranch.WithName(branch2))) + .WithBranch(stackBranch => stackBranch.WithName(branch1).WithChildBranch(b => b.WithName(branch2)))) .WithStack(stack => stack .WithName("Stack2") .WithRemoteUri(repo.RemoteUri) @@ -456,7 +444,6 @@ public async Task WhenNotSpecifyingRebaseOrMerge_AndUpdateSettingIsMerge_DoesSyn gitClient.ChangeBranch(branch1); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); inputProvider.Confirm(Questions.ConfirmSyncStack).Returns(true); @@ -496,8 +483,7 @@ public async Task WhenGitConfigValueIsSetToMerge_ButRebaseIsSpecified_DoesSyncUs .WithName("Stack1") .WithRemoteUri(repo.RemoteUri) .WithSourceBranch(sourceBranch) - .WithBranch(stackBranch => stackBranch.WithName(branch1)) - .WithBranch(stackBranch => stackBranch.WithName(branch2))) + .WithBranch(stackBranch => stackBranch.WithName(branch1).WithChildBranch(b => b.WithName(branch2)))) .WithStack(stack => stack .WithName("Stack2") .WithRemoteUri(repo.RemoteUri) @@ -511,7 +497,6 @@ public async Task WhenGitConfigValueIsSetToMerge_ButRebaseIsSpecified_DoesSyncUs gitClient.ChangeBranch(branch1); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); inputProvider.Confirm(Questions.ConfirmSyncStack).Returns(true); @@ -551,8 +536,7 @@ public async Task WhenGitConfigValueIsSetToRebase_ButMergeIsSpecified_DoesSyncUs .WithName("Stack1") .WithRemoteUri(repo.RemoteUri) .WithSourceBranch(sourceBranch) - .WithBranch(stackBranch => stackBranch.WithName(branch1)) - .WithBranch(stackBranch => stackBranch.WithName(branch2))) + .WithBranch(stackBranch => stackBranch.WithName(branch1).WithChildBranch(b => b.WithName(branch2)))) .WithStack(stack => stack .WithName("Stack2") .WithRemoteUri(repo.RemoteUri) diff --git a/src/Stack.Tests/Commands/Stack/CleanupStackCommandHandlerTests.cs b/src/Stack.Tests/Commands/Stack/CleanupStackCommandHandlerTests.cs index fba14c55..937fdee7 100644 --- a/src/Stack.Tests/Commands/Stack/CleanupStackCommandHandlerTests.cs +++ b/src/Stack.Tests/Commands/Stack/CleanupStackCommandHandlerTests.cs @@ -6,10 +6,11 @@ using Stack.Git; using Stack.Infrastructure; using Stack.Tests.Helpers; +using Xunit.Abstractions; namespace Stack.Tests.Commands.Stack; -public class CleanupStackCommandHandlerTests +public class CleanupStackCommandHandlerTests(ITestOutputHelper testOutputHelper) { [Fact] public async Task WhenBranchExistsLocally_ButHasNotBeenPushedToTheRemote_BranchIsNotDeletedLocally() @@ -37,13 +38,11 @@ public async Task WhenBranchExistsLocally_ButHasNotBeenPushedToTheRemote_BranchI .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new CleanupStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - logger.WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())).Do(ci => ci.ArgAt(1)()); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); inputProvider.Confirm(Questions.ConfirmDeleteBranches).Returns(true); @@ -82,13 +81,12 @@ public async Task WhenBranchExistsLocally_AndHasBeenDeletedFromTheRemote_BranchI .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new CleanupStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); var remoteUri = Some.HttpsUri().ToString(); - logger.WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())).Do(ci => ci.ArgAt(1)()); inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); inputProvider.Confirm(Questions.ConfirmDeleteBranches).Returns(true); @@ -126,13 +124,11 @@ public async Task WhenBranchExistsLocally_AndInRemote_BranchIsNotDeletedLocally( .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new CleanupStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - logger.WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())).Do(ci => ci.ArgAt(1)()); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); inputProvider.Confirm(Questions.ConfirmDeleteBranches).Returns(true); @@ -169,13 +165,11 @@ public async Task WhenConfirmationIsFalse_DoesNotDeleteAnyBranches() .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new CleanupStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - logger.WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())).Do(ci => ci.ArgAt(1)()); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); inputProvider.Confirm(Questions.ConfirmDeleteBranches).Returns(false); @@ -212,13 +206,11 @@ public async Task WhenStackNameIsProvided_ItIsNotAskedFor() .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new CleanupStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - logger.WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())).Do(ci => ci.ArgAt(1)()); - inputProvider.Confirm(Questions.ConfirmDeleteBranches).Returns(true); // Act @@ -254,12 +246,11 @@ public async Task WhenStackNameIsProvided_ButStackDoesNotExist_Throws() .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new CleanupStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - inputProvider.Confirm(Questions.ConfirmDeleteBranches).Returns(true); // Act and assert @@ -292,13 +283,11 @@ public async Task WhenOnlyASingleStackExists_StackIsSelectedAutomatically() .WithBranch(branch => branch.WithName(branchToKeep))) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new CleanupStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - logger.WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())).Do(ci => ci.ArgAt(1)()); - inputProvider.Confirm(Questions.ConfirmDeleteBranches).Returns(true); // Act @@ -336,13 +325,11 @@ public async Task WhenConfirmIsProvided_DoesNotAskForConfirmation_DeletesBranche .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new CleanupStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - logger.WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())).Do(ci => ci.ArgAt(1)()); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); // Act diff --git a/src/Stack.Tests/Commands/Stack/DeleteStackCommandHandlerTests.cs b/src/Stack.Tests/Commands/Stack/DeleteStackCommandHandlerTests.cs index f687bae1..f2cb1d4c 100644 --- a/src/Stack.Tests/Commands/Stack/DeleteStackCommandHandlerTests.cs +++ b/src/Stack.Tests/Commands/Stack/DeleteStackCommandHandlerTests.cs @@ -6,10 +6,11 @@ using Stack.Git; using Stack.Infrastructure; using Stack.Tests.Helpers; +using Xunit.Abstractions; namespace Stack.Tests.Commands.Stack; -public class DeleteStackCommandHandlerTests +public class DeleteStackCommandHandlerTests(ITestOutputHelper testOutputHelper) { [Fact] public async Task WhenNoInputsAreProvided_AsksForName_AndConfirmation_AndDeletesStack() @@ -29,13 +30,11 @@ public async Task WhenNoInputsAreProvided_AsksForName_AndConfirmation_AndDeletes .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new DeleteStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - logger.WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())).Do(ci => ci.ArgAt(1)()); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); inputProvider.Confirm(Questions.ConfirmDeleteStack).Returns(true); @@ -67,13 +66,11 @@ public async Task WhenConfirmationIsFalse_DoesNotDeleteStack() .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new DeleteStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - logger.WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())).Do(ci => ci.ArgAt(1)()); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); inputProvider.Confirm(Questions.ConfirmDeleteStack).Returns(false); @@ -106,13 +103,11 @@ public async Task WhenNameIsProvided_AsksForConfirmation_AndDeletesStack() .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new DeleteStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - logger.WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())).Do(ci => ci.ArgAt(1)()); - inputProvider.Confirm(Questions.ConfirmDeleteStack).Returns(true); // Act @@ -145,7 +140,7 @@ public async Task WhenStackDoesNotExist_Throws() .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new DeleteStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); @@ -189,13 +184,11 @@ public async Task WhenThereAreLocalBranchesThatAreDeletedInTheRemote_AsksToClean .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new DeleteStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - logger.WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())).Do(ci => ci.ArgAt(1)()); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); inputProvider.Confirm(Questions.ConfirmDeleteStack).Returns(true); inputProvider.Confirm(Questions.ConfirmDeleteBranches).Returns(true); @@ -225,13 +218,11 @@ public async Task WhenOnlyOneStackExists_DoesNotAskForStackName() .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new DeleteStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - logger.WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())).Do(ci => ci.ArgAt(1)()); - inputProvider.Confirm(Questions.ConfirmDeleteStack).Returns(true); // Act @@ -261,13 +252,11 @@ public async Task WhenConfirmIsProvided_DoesNotAskForConfirmation_DeletesStack() .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new DeleteStackCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - logger.WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())).Do(ci => ci.ArgAt(1)()); - inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); // Act diff --git a/src/Stack.Tests/Commands/Stack/NewStackCommandHandlerTests.cs b/src/Stack.Tests/Commands/Stack/NewStackCommandHandlerTests.cs index c00661ab..fd299471 100644 --- a/src/Stack.Tests/Commands/Stack/NewStackCommandHandlerTests.cs +++ b/src/Stack.Tests/Commands/Stack/NewStackCommandHandlerTests.cs @@ -6,12 +6,12 @@ using Stack.Git; using Stack.Infrastructure; using Stack.Tests.Helpers; +using Xunit.Abstractions; namespace Stack.Tests.Commands.Stack; -public class NewStackCommandHandlerTests +public class NewStackCommandHandlerTests(ITestOutputHelper testOutputHelper) { - [Fact] public async Task WithAnExistingBranch_TheStackIsCreatedAndTheCurrentBranchIsChanged() { @@ -25,11 +25,10 @@ public async Task WithAnExistingBranch_TheStackIsCreatedAndTheCurrentBranchIsCha var stackConfig = new TestStackConfigBuilder().Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new NewStackCommandHandler(inputProvider, logger, gitClient, stackConfig); - inputProvider.Text(Questions.StackName).Returns("Stack1"); inputProvider.Select(Questions.SelectSourceBranch, Arg.Any()).Returns(sourceBranch); inputProvider.Select(Questions.AddOrCreateBranch, Arg.Any(), Arg.Any>()).Returns(BranchAction.Add); @@ -60,14 +59,12 @@ public async Task WithNoBranch_TheStackIsCreatedAndTheCurrentBranchIsNotChanged( var stackConfig = new TestStackConfigBuilder().Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new NewStackCommandHandler(inputProvider, logger, gitClient, stackConfig); gitClient.ChangeBranch(existingBranch); - - inputProvider.Text(Questions.StackName).Returns("Stack1"); inputProvider.Select(Questions.SelectSourceBranch, Arg.Any()).Returns(sourceBranch); inputProvider.Select(Questions.AddOrCreateBranch, Arg.Any(), Arg.Any>()).Returns(BranchAction.None); @@ -95,11 +92,10 @@ public async Task WhenStackNameIsProvidedInInputs_TheProviderIsNotAskedForAName_ var stackConfig = new TestStackConfigBuilder().Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new NewStackCommandHandler(inputProvider, logger, gitClient, stackConfig); - inputProvider.Select(Questions.SelectSourceBranch, Arg.Any()).Returns(sourceBranch); inputProvider.Select(Questions.AddOrCreateBranch, Arg.Any(), Arg.Any>()).Returns(BranchAction.None); @@ -128,11 +124,10 @@ public async Task WhenSourceBranchIsProvidedInInputs_TheProviderIsNotAskedForThe var stackConfig = new TestStackConfigBuilder().Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new NewStackCommandHandler(inputProvider, logger, gitClient, stackConfig); - inputProvider.Text(Questions.StackName).Returns("Stack1"); inputProvider.Select(Questions.AddOrCreateBranch, Arg.Any(), Arg.Any>()).Returns(BranchAction.None); @@ -162,11 +157,10 @@ public async Task WhenBranchNameIsProvidedInInputs_TheProviderIsNotAskedForTheBr var stackConfig = new TestStackConfigBuilder().Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new NewStackCommandHandler(inputProvider, logger, gitClient, stackConfig); - inputProvider.Text(Questions.StackName).Returns("Stack1"); inputProvider.Select(Questions.SelectSourceBranch, Arg.Any()).Returns(sourceBranch); // Note there shouldn't be any more inputs required at all @@ -200,11 +194,10 @@ public async Task WhenAStackHasANameWithMultipleWords_SuggestsAGoodDefaultNewBra var stackConfig = new TestStackConfigBuilder().Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new NewStackCommandHandler(inputProvider, logger, gitClient, stackConfig); - inputProvider.Text(Questions.StackName).Returns("A stack with multiple words"); inputProvider.Select(Questions.SelectSourceBranch, Arg.Any()).Returns(sourceBranch); inputProvider.Select(Questions.AddOrCreateBranch, Arg.Any(), Arg.Any>()).Returns(BranchAction.Create); @@ -234,11 +227,10 @@ public async Task WithANewBranch_TheStackIsCreatedAndTheBranchExistsOnTheRemote( var stackConfig = new TestStackConfigBuilder().Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new NewStackCommandHandler(inputProvider, logger, gitClient, stackConfig); - inputProvider.Text(Questions.StackName).Returns("Stack1"); inputProvider.Select(Questions.SelectSourceBranch, Arg.Any()).Returns(sourceBranch); inputProvider.Select(Questions.AddOrCreateBranch, Arg.Any(), Arg.Any>()).Returns(BranchAction.Create); @@ -268,7 +260,7 @@ public async Task WithANewBranch_AndThePushFails_TheStackIsStillCreatedSuccessfu var stackConfig = new TestStackConfigBuilder().Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = Substitute.ForPartsOf(logger, repo.GitClientSettings); var handler = new NewStackCommandHandler(inputProvider, logger, gitClient, stackConfig); @@ -276,7 +268,6 @@ public async Task WithANewBranch_AndThePushFails_TheStackIsStillCreatedSuccessfu .WhenForAnyArgs(gc => gc.PushNewBranch(Arg.Any())) .Throw(new Exception("Failed to push branch")); - inputProvider.Text(Questions.StackName).Returns("Stack1"); inputProvider.Select(Questions.SelectSourceBranch, Arg.Any()).Returns(sourceBranch); inputProvider.Select(Questions.AddOrCreateBranch, Arg.Any(), Arg.Any>()).Returns(BranchAction.Create); diff --git a/src/Stack.Tests/Commands/Stack/StackStatusCommandHandlerTests.cs b/src/Stack.Tests/Commands/Stack/StackStatusCommandHandlerTests.cs index 64cdc9cd..cbb3c32b 100644 --- a/src/Stack.Tests/Commands/Stack/StackStatusCommandHandlerTests.cs +++ b/src/Stack.Tests/Commands/Stack/StackStatusCommandHandlerTests.cs @@ -6,10 +6,11 @@ using Stack.Tests.Helpers; using Stack.Infrastructure; using Stack.Commands.Helpers; +using Xunit.Abstractions; namespace Stack.Tests.Commands.Stack; -public class StackStatusCommandHandlerTests +public class StackStatusCommandHandlerTests(ITestOutputHelper testOutputHelper) { [Fact] public async Task WhenMultipleBranchesExistInAStack_AndOneHasAPullRequests_ReturnsStatus() @@ -41,13 +42,12 @@ public async Task WhenMultipleBranchesExistInAStack_AndOneHasAPullRequests_Retur .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new StackStatusCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); - logger.WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())).Do(ci => ci.ArgAt(1)()); var pr = new GitHubPullRequest(1, "PR title", "PR body", GitHubPullRequestStates.Open, Some.HttpsUri(), false); @@ -57,19 +57,21 @@ public async Task WhenMultipleBranchesExistInAStack_AndOneHasAPullRequests_Retur var response = await handler.Handle(new StackStatusCommandInputs(null, false, true)); // Assert - var expectedSourceBranch = new BranchDetailBase(sourceBranch, true, + var expectedSourceBranch = new SourceBranchDetail(sourceBranch, true, new Commit(tipOfSourceBranch.Sha[..7], tipOfSourceBranch.Message.Trim()), new RemoteTrackingBranchStatus($"origin/{sourceBranch}", true, 0, 0)); var expectedBranch1 = new BranchDetail(branch1, true, new Commit(tipOfBranch1.Sha[..7], tipOfBranch1.Message.Trim()), new RemoteTrackingBranchStatus($"origin/{branch1}", true, 0, 0), - pr, new ParentBranchStatus(expectedSourceBranch, 10, 5)); - var expectedBranch2 = new BranchDetail(branch2, true, - new Commit(tipOfBranch2.Sha[..7], tipOfBranch2.Message.Trim()), - new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), - null, new ParentBranchStatus(expectedBranch1, 1, 0)); - - var expectedStackDetail = new StackStatus("Stack1", expectedSourceBranch, [expectedBranch1, expectedBranch2]); + pr, new ParentBranchStatus(sourceBranch, 10, 5), + [ + new BranchDetail(branch2, true, + new Commit(tipOfBranch2.Sha[..7], tipOfBranch2.Message.Trim()), + new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), + null, new ParentBranchStatus(branch1, 1, 0), []) + ]); + + var expectedStackDetail = new StackStatus("Stack1", expectedSourceBranch, [expectedBranch1]); response.Stacks.Should().BeEquivalentTo([expectedStackDetail]); } @@ -103,13 +105,12 @@ public async Task WhenStackNameIsProvided_DoesNotAskForStack_ReturnsStatus() .WithSourceBranch(sourceBranch)) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new StackStatusCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); - logger.WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())).Do(ci => ci.ArgAt(1)()); var pr = new GitHubPullRequest(1, "PR title", "PR body", GitHubPullRequestStates.Open, Some.HttpsUri(), false); @@ -119,21 +120,22 @@ public async Task WhenStackNameIsProvided_DoesNotAskForStack_ReturnsStatus() var response = await handler.Handle(new StackStatusCommandInputs("Stack1", false, true)); // Assert - var expectedSourceBranch = new BranchDetailBase(sourceBranch, true, + var expectedSourceBranch = new SourceBranchDetail(sourceBranch, true, new Commit(tipOfSourceBranch.Sha[..7], tipOfSourceBranch.Message.Trim()), new RemoteTrackingBranchStatus($"origin/{sourceBranch}", true, 0, 0)); var expectedBranch1 = new BranchDetail(branch1, true, new Commit(tipOfBranch1.Sha[..7], tipOfBranch1.Message.Trim()), new RemoteTrackingBranchStatus($"origin/{branch1}", true, 0, 0), - pr, new ParentBranchStatus(expectedSourceBranch, 10, 5)); - - var expectedBranch2 = new BranchDetail(branch2, true, - new Commit(tipOfBranch2.Sha[..7], tipOfBranch2.Message.Trim()), - new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), - null, new ParentBranchStatus(expectedBranch1, 1, 0)); - - var expectedStackDetail = new StackStatus("Stack1", expectedSourceBranch, [expectedBranch1, expectedBranch2]); + pr, new ParentBranchStatus(sourceBranch, 10, 5), + [ + new BranchDetail(branch2, true, + new Commit(tipOfBranch2.Sha[..7], tipOfBranch2.Message.Trim()), + new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), + null, new ParentBranchStatus(branch1, 1, 0), []) + ]); + + var expectedStackDetail = new StackStatus("Stack1", expectedSourceBranch, [expectedBranch1]); response.Stacks.Should().BeEquivalentTo([expectedStackDetail]); inputProvider.ReceivedCalls().Should().BeEmpty(); @@ -173,15 +175,11 @@ public async Task WhenAllStacksAreRequested_ReturnsStatusOfEachStack() .WithBranch(b => b.WithName(branch3))) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new StackStatusCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - logger - .WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())) - .Do(ci => ci.ArgAt(1)()); - var pr = new GitHubPullRequest(1, "PR title", "PR body", GitHubPullRequestStates.Open, Some.HttpsUri(), false); gitHubClient @@ -192,26 +190,27 @@ public async Task WhenAllStacksAreRequested_ReturnsStatusOfEachStack() var response = await handler.Handle(new StackStatusCommandInputs(null, true, true)); // Assert - var expectedSourceBranch = new BranchDetailBase(sourceBranch, true, + var expectedSourceBranch = new SourceBranchDetail(sourceBranch, true, new Commit(tipOfSourceBranch.Sha[..7], tipOfSourceBranch.Message.Trim()), new RemoteTrackingBranchStatus($"origin/{sourceBranch}", true, 0, 0)); var expectedBranch1 = new BranchDetail(branch1, true, new Commit(tipOfBranch1.Sha[..7], tipOfBranch1.Message.Trim()), new RemoteTrackingBranchStatus($"origin/{branch1}", true, 0, 0), - pr, new ParentBranchStatus(expectedSourceBranch, 10, 5)); - - var expectedBranch2 = new BranchDetail(branch2, true, - new Commit(tipOfBranch2.Sha[..7], tipOfBranch2.Message.Trim()), - new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), - null, new ParentBranchStatus(expectedBranch1, 1, 0)); + pr, new ParentBranchStatus(sourceBranch, 10, 5), + [ + new BranchDetail(branch2, true, + new Commit(tipOfBranch2.Sha[..7], tipOfBranch2.Message.Trim()), + new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), + null, new ParentBranchStatus(branch1, 1, 0), []) + ]); - var expectedStackDetail1 = new StackStatus("Stack1", expectedSourceBranch, [expectedBranch1, expectedBranch2]); + var expectedStackDetail1 = new StackStatus("Stack1", expectedSourceBranch, [expectedBranch1]); var expectedBranch3 = new BranchDetail(branch3, true, new Commit(tipOfBranch3.Sha[..7], tipOfBranch3.Message.Trim()), new RemoteTrackingBranchStatus($"origin/{branch3}", true, 0, 0), - null, new ParentBranchStatus(expectedSourceBranch, 3, 5)); + null, new ParentBranchStatus(sourceBranch, 3, 5), []); var expectedStackDetail2 = new StackStatus("Stack2", expectedSourceBranch, [expectedBranch3]); @@ -257,13 +256,11 @@ public async Task WhenAllStacksAreRequested_WithStacksInMultipleRepositories_Ret .WithBranch(b => b.WithName(Some.BranchName()))) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new StackStatusCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - logger.WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())).Do(ci => ci.ArgAt(1)()); - var pr = new GitHubPullRequest(1, "PR title", "PR body", GitHubPullRequestStates.Open, Some.HttpsUri(), false); gitHubClient.GetPullRequest(branch1).Returns(pr); @@ -272,26 +269,27 @@ public async Task WhenAllStacksAreRequested_WithStacksInMultipleRepositories_Ret var response = await handler.Handle(new StackStatusCommandInputs(null, true, true)); // Assert - var expectedSourceBranch = new BranchDetailBase(sourceBranch, true, + var expectedSourceBranch = new SourceBranchDetail(sourceBranch, true, new Commit(tipOfSourceBranch.Sha[..7], tipOfSourceBranch.Message.Trim()), new RemoteTrackingBranchStatus($"origin/{sourceBranch}", true, 0, 0)); var expectedBranch1 = new BranchDetail(branch1, true, new Commit(tipOfBranch1.Sha[..7], tipOfBranch1.Message.Trim()), new RemoteTrackingBranchStatus($"origin/{branch1}", true, 0, 0), - pr, new ParentBranchStatus(expectedSourceBranch, 10, 5)); + pr, new ParentBranchStatus(sourceBranch, 10, 5), + [ + new BranchDetail(branch2, true, + new Commit(tipOfBranch2.Sha[..7], tipOfBranch2.Message.Trim()), + new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), + null, new ParentBranchStatus(branch1, 1, 0), []) + ]); - var expectedBranch2 = new BranchDetail(branch2, true, - new Commit(tipOfBranch2.Sha[..7], tipOfBranch2.Message.Trim()), - new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), - null, new ParentBranchStatus(expectedBranch1, 1, 0)); - - var expectedStackDetail1 = new StackStatus("Stack1", expectedSourceBranch, [expectedBranch1, expectedBranch2]); + var expectedStackDetail1 = new StackStatus("Stack1", expectedSourceBranch, [expectedBranch1]); var expectedBranch3 = new BranchDetail(branch3, true, new Commit(tipOfBranch3.Sha[..7], tipOfBranch3.Message.Trim()), new RemoteTrackingBranchStatus($"origin/{branch3}", true, 0, 0), - null, new ParentBranchStatus(expectedSourceBranch, 3, 5)); + null, new ParentBranchStatus(sourceBranch, 3, 5), []); var expectedStackDetail2 = new StackStatus("Stack2", expectedSourceBranch, [expectedBranch3]); @@ -327,7 +325,7 @@ public async Task WhenStackNameIsProvided_ButStackDoesNotExist_Throws() .WithBranch(b => b.WithName(aThirdBranch))) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new StackStatusCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); @@ -371,15 +369,12 @@ public async Task WhenMultipleBranchesExistInAStack_AndOneNoLongerExistsOnTheRem .WithBranch(b => b.WithName(branch3))) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new StackStatusCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); - logger - .WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())) - .Do(ci => ci.ArgAt(1)()); var pr = new GitHubPullRequest(1, "PR title", "PR body", GitHubPullRequestStates.Open, Some.HttpsUri(), false); @@ -391,20 +386,21 @@ public async Task WhenMultipleBranchesExistInAStack_AndOneNoLongerExistsOnTheRem var response = await handler.Handle(new StackStatusCommandInputs(null, false, true)); // Assert - var expectedSourceBranch = new BranchDetailBase(sourceBranch, true, + var expectedSourceBranch = new SourceBranchDetail(sourceBranch, true, new Commit(tipOfSourceBranch.Sha[..7], tipOfSourceBranch.Message.Trim()), new RemoteTrackingBranchStatus($"origin/{sourceBranch}", true, 0, 0)); var expectedBranch1 = new BranchDetail(branch1, true, new Commit(tipOfBranch1.Sha[..7], tipOfBranch1.Message.Trim()), - null, null, new ParentBranchStatus(expectedSourceBranch, 0, 0)); - - var expectedBranch2 = new BranchDetail(branch2, true, - new Commit(tipOfBranch2.Sha[..7], tipOfBranch2.Message.Trim()), - new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), - pr, new ParentBranchStatus(expectedSourceBranch, 11, 0)); - - var expectedStackDetail = new StackStatus("Stack1", expectedSourceBranch, [expectedBranch1, expectedBranch2]); + null, null, new ParentBranchStatus(sourceBranch, 0, 0), + [ + new BranchDetail(branch2, true, + new Commit(tipOfBranch2.Sha[..7], tipOfBranch2.Message.Trim()), + new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), + pr, new ParentBranchStatus(sourceBranch, 11, 0), []) + ]); + + var expectedStackDetail = new StackStatus("Stack1", expectedSourceBranch, [expectedBranch1]); response.Stacks.Should().BeEquivalentTo([expectedStackDetail]); } @@ -437,15 +433,12 @@ public async Task WhenMultipleBranchesExistInAStack_AndOneNoLongerExistsOnTheRem .WithBranch(b => b.WithName(branch3))) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new StackStatusCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); - logger - .WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())) - .Do(ci => ci.ArgAt(1)()); var pr = new GitHubPullRequest(1, "PR title", "PR body", GitHubPullRequestStates.Open, Some.HttpsUri(), false); @@ -457,18 +450,19 @@ public async Task WhenMultipleBranchesExistInAStack_AndOneNoLongerExistsOnTheRem var response = await handler.Handle(new StackStatusCommandInputs(null, false, true)); // Assert - var expectedSourceBranch = new BranchDetailBase(sourceBranch, true, + var expectedSourceBranch = new SourceBranchDetail(sourceBranch, true, new Commit(tipOfSourceBranch.Sha[..7], tipOfSourceBranch.Message.Trim()), new RemoteTrackingBranchStatus($"origin/{sourceBranch}", true, 0, 0)); - var expectedBranch1 = new BranchDetail(branch1, false, null, null, null, null); + var expectedBranch1 = new BranchDetail(branch1, false, null, null, null, null, + [ + new BranchDetail(branch2, true, + new Commit(tipOfBranch2.Sha[..7], tipOfBranch2.Message.Trim()), + new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), + pr, new ParentBranchStatus(sourceBranch, 1, 0), []) + ]); - var expectedBranch2 = new BranchDetail(branch2, true, - new Commit(tipOfBranch2.Sha[..7], tipOfBranch2.Message.Trim()), - new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), - pr, new ParentBranchStatus(expectedSourceBranch, 1, 0)); - - var expectedStackDetail = new StackStatus("Stack1", expectedSourceBranch, [expectedBranch1, expectedBranch2]); + var expectedStackDetail = new StackStatus("Stack1", expectedSourceBranch, [expectedBranch1]); response.Stacks.Should().BeEquivalentTo([expectedStackDetail]); } @@ -498,15 +492,11 @@ public async Task WhenOnlyOneStackExists_DoesNotAskForStackName_ReturnsStatus() .WithBranch(b1 => b1.WithName(branch1).WithChildBranch(b2 => b2.WithName(branch2)))) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var gitHubClient = Substitute.For(); var handler = new StackStatusCommandHandler(inputProvider, logger, gitClient, gitHubClient, stackConfig); - logger - .WhenForAnyArgs(o => o.Status(Arg.Any(), Arg.Any())) - .Do(ci => ci.ArgAt(1)()); - var pr = new GitHubPullRequest(1, "PR title", "PR body", GitHubPullRequestStates.Open, Some.HttpsUri(), false); gitHubClient @@ -517,19 +507,21 @@ public async Task WhenOnlyOneStackExists_DoesNotAskForStackName_ReturnsStatus() var response = await handler.Handle(new StackStatusCommandInputs(null, false, true)); // Assert - var expectedSourceBranch = new BranchDetailBase(sourceBranch, true, + var expectedSourceBranch = new SourceBranchDetail(sourceBranch, true, new Commit(tipOfSourceBranch.Sha[..7], tipOfSourceBranch.Message.Trim()), new RemoteTrackingBranchStatus($"origin/{sourceBranch}", true, 0, 0)); var expectedBranch1 = new BranchDetail(branch1, true, new Commit(tipOfBranch1.Sha[..7], tipOfBranch1.Message.Trim()), new RemoteTrackingBranchStatus($"origin/{branch1}", true, 0, 0), - pr, new ParentBranchStatus(expectedSourceBranch, 10, 5)); - var expectedBranch2 = new BranchDetail(branch2, true, - new Commit(tipOfBranch2.Sha[..7], tipOfBranch2.Message.Trim()), - new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), - null, new ParentBranchStatus(expectedBranch1, 1, 0)); - - var expectedStackDetail = new StackStatus("Stack1", expectedSourceBranch, [expectedBranch1, expectedBranch2]); + pr, new ParentBranchStatus(sourceBranch, 10, 5), + [ + new BranchDetail(branch2, true, + new Commit(tipOfBranch2.Sha[..7], tipOfBranch2.Message.Trim()), + new RemoteTrackingBranchStatus($"origin/{branch2}", true, 0, 0), + null, new ParentBranchStatus(branch1, 1, 0), []) + ]); + + var expectedStackDetail = new StackStatus("Stack1", expectedSourceBranch, [expectedBranch1]); response.Stacks.Should().BeEquivalentTo([expectedStackDetail]); inputProvider.DidNotReceive().Select(Questions.SelectStack, Arg.Any()); diff --git a/src/Stack.Tests/Commands/Stack/StackSwitchCommandHandlerTests.cs b/src/Stack.Tests/Commands/Stack/StackSwitchCommandHandlerTests.cs index 03692038..111eef13 100644 --- a/src/Stack.Tests/Commands/Stack/StackSwitchCommandHandlerTests.cs +++ b/src/Stack.Tests/Commands/Stack/StackSwitchCommandHandlerTests.cs @@ -6,10 +6,11 @@ using Stack.Git; using Stack.Infrastructure; using Stack.Tests.Helpers; +using Xunit.Abstractions; namespace Stack.Tests.Commands.Stack; -public class StackSwitchCommandHandlerTests +public class StackSwitchCommandHandlerTests(ITestOutputHelper testOutputHelper) { [Fact] public async Task WhenNoInputsAreProvided_AsksForBranch_ChangesToBranch() @@ -36,13 +37,12 @@ public async Task WhenNoInputsAreProvided_AsksForBranch_ChangesToBranch() .WithBranch(b => b.WithName(anotherBranch))) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new StackSwitchCommandHandler(inputProvider, gitClient, stackConfig); gitClient.ChangeBranch(sourceBranch); - inputProvider.SelectGrouped(Questions.SelectBranch, Arg.Any[]>()).Returns(branchToSwitchTo); // Act @@ -77,13 +77,12 @@ public async Task WhenBranchIsProvided_DoesNotAskForBranch_ChangesToBranch() .WithBranch(b => b.WithName(anotherBranch))) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new StackSwitchCommandHandler(inputProvider, gitClient, stackConfig); gitClient.ChangeBranch(sourceBranch); - // Act await handler.Handle(new StackSwitchCommandInputs(branchToSwitchTo)); @@ -117,13 +116,12 @@ public async Task WhenBranchIsProvided_AndBranchDoesNotExist_Throws() .WithBranch(b => b.WithName(anotherBranch))) .Build(); var inputProvider = Substitute.For(); - var logger = Substitute.For(); + var logger = new TestLogger(testOutputHelper); var gitClient = new GitClient(logger, repo.GitClientSettings); var handler = new StackSwitchCommandHandler(inputProvider, gitClient, stackConfig); gitClient.ChangeBranch(sourceBranch); - // Act and assert var invalidBranchName = Some.BranchName(); await handler.Invoking(h => h.Handle(new StackSwitchCommandInputs(invalidBranchName))) diff --git a/src/Stack.Tests/Commands/Stack/UpdateStackCommandHandlerTests.cs b/src/Stack.Tests/Commands/Stack/UpdateStackCommandHandlerTests.cs index d650eaab..d699aad5 100644 --- a/src/Stack.Tests/Commands/Stack/UpdateStackCommandHandlerTests.cs +++ b/src/Stack.Tests/Commands/Stack/UpdateStackCommandHandlerTests.cs @@ -96,7 +96,7 @@ public async Task WhenABranchInTheStackNoLongerExistsOnTheRemote_SkipsOverUpdati inputProvider.Select(Questions.SelectStack, Arg.Any()).Returns("Stack1"); // Act - await handler.Handle(new UpdateStackCommandInputs(null, false, false)); + await handler.Handle(new UpdateStackCommandInputs(null, false, true)); // Assert repo.GetCommitsReachableFromBranch(branch2).Should().Contain(tipOfSourceBranch); @@ -141,7 +141,7 @@ public async Task WhenABranchInTheStackExistsOnTheRemote_ButThePullRequestIsMerg gitHubClient.GetPullRequest(branch1).Returns(new GitHubPullRequest(1, Some.Name(), Some.Name(), GitHubPullRequestStates.Merged, Some.HttpsUri(), false)); // Act - await handler.Handle(new UpdateStackCommandInputs(null, false, false)); + await handler.Handle(new UpdateStackCommandInputs(null, false, true)); // Assert repo.GetCommitsReachableFromBranch(branch2).Should().Contain(tipOfSourceBranch); diff --git a/src/Stack.Tests/Helpers/TestLogger.cs b/src/Stack.Tests/Helpers/TestLogger.cs index a04cfc69..f37228b8 100644 --- a/src/Stack.Tests/Helpers/TestLogger.cs +++ b/src/Stack.Tests/Helpers/TestLogger.cs @@ -44,4 +44,14 @@ public void Warning(string message) { testOutputHelper.WriteLine($"WARNING: {message}"); } + + public void Tree(Tree tree) + { + testOutputHelper.WriteLine($"TREE: {tree.Header}"); + foreach (var child in tree.Children) + { + testOutputHelper.WriteLine($" {child.Value}"); + // TODO: Handle child nodes if needed + } + } } diff --git a/src/Stack/Commands/Helpers/StackHelpers.cs b/src/Stack/Commands/Helpers/StackHelpers.cs index bf904bef..d6260f64 100644 --- a/src/Stack/Commands/Helpers/StackHelpers.cs +++ b/src/Stack/Commands/Helpers/StackHelpers.cs @@ -1,12 +1,130 @@ using System.Text; +using MoreLinq; using Spectre.Console; using Stack.Config; using Stack.Git; using Stack.Infrastructure; +using static Stack.Commands.CreatePullRequestsCommandHandler; namespace Stack.Commands.Helpers; -public record StackStatus(string Name, BranchDetailBase SourceBranch, BranchDetail[] Branches); +public record StackStatus(string Name, SourceBranchDetail SourceBranch, List Branches) +{ + public List> GetAllBranchLines() + { + var allLines = new List>(); + foreach (var branch in Branches) + { + allLines.AddRange(branch.GetAllPaths()); + } + return allLines; + } + + public List GetAllBranches() + { + var branchesToReturn = new List(); + foreach (var branch in Branches) + { + branchesToReturn.Add(branch); + branchesToReturn.AddRange(GetAllBranches(branch)); + } + + return branchesToReturn; + } + + static List GetAllBranches(BranchDetail branch) + { + var branchesToReturn = new List(); + foreach (var child in branch.Children) + { + branchesToReturn.Add(child); + branchesToReturn.AddRange(GetAllBranches(child)); + } + + return branchesToReturn; + } + + public BranchDetail? GetDeepestActiveBranchInSingleTree() + { + foreach (var branch in Branches) + { + var deepestBranch = GetDeepestActiveBranch(branch); + if (deepestBranch is not null) + { + return deepestBranch; + } + } + + return null; + } + + public BranchDetail? GetDeepestActiveBranch(BranchDetail branch) + { + if (branch.IsActive && branch.Children.Count == 0) + { + return branch; + } + + foreach (var child in branch.Children) + { + if (child.IsActive) + { + var deepestChild = GetDeepestActiveBranch(child); + if (deepestChild is not null) + { + return deepestChild; + } + } + } + + return null; + } + + public BranchDetail? WalkBranches(Func predicate) + { + static BranchDetail? WalkBranch(Func predicate, BranchDetail branch) + { + var action = predicate(branch); + if (action == WalkAction.Return) + { + return branch; + } + else if (action == WalkAction.Skip) + { + return null; + } + + foreach (var child in branch.Children) + { + var result = WalkBranch(predicate, child); + if (result is not null) + { + return result; + } + } + + return null; + } + + foreach (var branch in Branches) + { + var result = WalkBranch(predicate, branch); + if (result is not null) + { + return result; + } + } + + return null; + } +} + +public enum WalkAction +{ + Continue, + Return, + Skip +} public record RemoteTrackingBranchStatus(string Name, bool Exists, int Ahead, int Behind); @@ -17,23 +135,48 @@ public record BranchDetailBase(string Name, bool Exists, Commit? Tip, RemoteTrac public int BehindRemote => RemoteTrackingBranch?.Behind ?? 0; } +public record SourceBranchDetail(string Name, bool Exists, Commit? Tip, RemoteTrackingBranchStatus? RemoteTrackingBranch) : BranchDetailBase(Name, Exists, Tip, RemoteTrackingBranch); + public record BranchDetail( string Name, bool Exists, Commit? Tip, RemoteTrackingBranchStatus? RemoteTrackingBranch, GitHubPullRequest? PullRequest, - ParentBranchStatus? Parent) : BranchDetailBase(Name, Exists, Tip, RemoteTrackingBranch) + ParentBranchStatus? Parent, + List Children) : BranchDetailBase(Name, Exists, Tip, RemoteTrackingBranch) { public override bool IsActive => base.IsActive && (PullRequest is null || PullRequest.State != GitHubPullRequestStates.Merged); public bool CouldBeCleanedUp => Exists && ((RemoteTrackingBranch is not null && !RemoteTrackingBranch.Exists) || (PullRequest is not null && PullRequest.State == GitHubPullRequestStates.Merged)); public bool HasPullRequest => PullRequest is not null && PullRequest.State != GitHubPullRequestStates.Closed; public int AheadOfParent => Parent?.Ahead ?? 0; public int BehindParent => Parent?.Behind ?? 0; - public string ParentBranchName => Parent?.Branch.Name ?? string.Empty; + public string ParentBranchName => Parent?.Name ?? string.Empty; + + public List> GetAllPaths() + { + var result = new List>(); + if (Children.Count == 0) + { + result.Add([this]); + } + else + { + foreach (var child in Children) + { + foreach (var path in child.GetAllPaths()) + { + var newPath = new List { this }; + newPath.AddRange(path); + result.Add(newPath); + } + } + } + return result; + } } -public record ParentBranchStatus(BranchDetailBase Branch, int Ahead, int Behind); +public record ParentBranchStatus(string Name, int Ahead, int Behind); public static class StackHelpers { @@ -78,7 +221,7 @@ static void EvaluateBranchStatusDetails(ILogger logger, IGitClient gitClient, IG continue; } - var sourceBranch = new BranchDetailBase( + var sourceBranch = new SourceBranchDetail( stack.SourceBranch, true, sourceBranchStatus.Tip, @@ -93,26 +236,24 @@ sourceBranchStatus.RemoteTrackingBranchName is not null foreach (var branch in stack.Branches) { - var branchDetails = AddBranchDetailsForAllChildren(gitClient, gitHubClient, includePullRequestStatus, branchStatuses, sourceBranch, branch); - stackBranches.AddRange(branchDetails); + var branchDetail = AddBranchDetailsForAllChildren(gitClient, gitHubClient, includePullRequestStatus, branchStatuses, sourceBranch, branch); + stackBranches.Add(branchDetail); } stacksToReturnStatusFor.Add(new StackStatus(stack.Name, sourceBranch, [.. stackBranches])); } - static List AddBranchDetailsForAllChildren(IGitClient gitClient, IGitHubClient gitHubClient, bool includePullRequestStatus, Dictionary branchStatuses, BranchDetailBase parentBranch, Branch branch) + static BranchDetail AddBranchDetailsForAllChildren(IGitClient gitClient, IGitHubClient gitHubClient, bool includePullRequestStatus, Dictionary branchStatuses, BranchDetailBase parentBranch, Branch branch) { - var branchDetails = new List(); var branchDetail = CreateBranchDetail(gitClient, gitHubClient, includePullRequestStatus, branchStatuses, parentBranch, branch); - branchDetails.Add(branchDetail); foreach (var childBranch in branch.Children) { var childBranchDetails = AddBranchDetailsForAllChildren(gitClient, gitHubClient, includePullRequestStatus, branchStatuses, branchDetail.IsActive ? branchDetail : parentBranch, childBranch); - branchDetails.AddRange(childBranchDetails); + branchDetail.Children.Add(childBranchDetails); } - return branchDetails; + return branchDetail; } static BranchDetail CreateBranchDetail(IGitClient gitClient, IGitHubClient gitHubClient, bool includePullRequestStatus, Dictionary branchStatuses, BranchDetailBase parentBranch, Branch branch) @@ -141,11 +282,19 @@ branchStatus.RemoteTrackingBranchName is not null branchStatus.Behind) : null, pullRequest, - new ParentBranchStatus(parentBranch, aheadOfParent, behindParent)); + new ParentBranchStatus(parentBranch.Name, aheadOfParent, behindParent), + []); } else { - return new BranchDetail(branch.Name, false, null, null, null, null); + GitHubPullRequest? pullRequest = null; + + if (includePullRequestStatus) + { + pullRequest = gitHubClient.GetPullRequest(branch.Name); + } + + return new BranchDetail(branch.Name, false, null, null, pullRequest, null, []); } } } @@ -171,32 +320,40 @@ public static StackStatus GetStackStatus( } public static void OutputStackStatus( - List stacks, + SchemaVersion schemaVersion, + List statuses, ILogger logger) { - foreach (var stack in stacks) + foreach (var status in statuses) { - OutputStackStatus(stack, logger); + OutputStackStatus(schemaVersion, status, logger); logger.NewLine(); } } public static void OutputStackStatus( - StackStatus stack, + SchemaVersion schemaVersion, + StackStatus status, ILogger logger) { - var header = GetBranchStatusOutput(stack.SourceBranch); - var items = new List(); + var header = GetBranchStatusOutput(status.SourceBranch); + var items = new List>(); - foreach (var branch in stack.Branches) + foreach (var branch in status.Branches) { items.Add(GetBranchAndPullRequestStatusOutput(branch)); } - logger.Information(stack.Name.Stack()); - logger.Tree(header, [.. items]); + + if (schemaVersion == SchemaVersion.V1 && items.Count > 0) + { + items = [.. MoreEnumerable.TraverseDepthFirst(items.First(), i => i.Children).Select(i => new TreeItem(i.Value, []))]; + } + + logger.Information(status.Name.Stack()); + logger.Tree(new Tree(header, [.. items])); } - public static string GetBranchAndPullRequestStatusOutput(BranchDetail branch) + public static TreeItem GetBranchAndPullRequestStatusOutput(BranchDetail branch) { var branchNameBuilder = new StringBuilder(); branchNameBuilder.Append(GetBranchStatusOutput(branch)); @@ -206,7 +363,31 @@ public static string GetBranchAndPullRequestStatusOutput(BranchDetail branch) branchNameBuilder.Append($" {branch.PullRequest.GetPullRequestDisplay()}"); } - return branchNameBuilder.ToString(); + var treeItemValue = branchNameBuilder.ToString(); + var children = branch.Children + .Select(GetBranchAndPullRequestStatusOutput) + .ToList(); + + return new TreeItem(treeItemValue, children); + } + + public static TreeItem GetBranchAndPullRequestInformation(BranchDetail branch, List pullRequestInformation) + { + var branchNameBuilder = new StringBuilder(); + branchNameBuilder.Append(GetBranchStatusOutput(branch)); + var prInformationForBranch = pullRequestInformation.FirstOrDefault(a => a.HeadBranch == branch.Name); + + if (prInformationForBranch is not null) + { + branchNameBuilder.Append($" {$"*NEW* {prInformationForBranch.Title}".Highlighted()}{(prInformationForBranch.Draft == true ? " (draft)".Muted() : string.Empty)}"); + } + + var treeItemValue = branchNameBuilder.ToString(); + var children = branch.Children + .Select(b => GetBranchAndPullRequestInformation(b, pullRequestInformation)) + .ToList(); + + return new TreeItem(treeItemValue, children); } public static string GetBranchStatusOutput(BranchDetailBase branch) @@ -250,7 +431,7 @@ public static string GetBranchStatusOutput(BranchDetailBase branch) branchNameBuilder.Append(" (remote branch deleted)".Muted()); } - if (branch.Tip is not null) + if (branch.Exists && branch.Tip is not null) { branchNameBuilder.Append($" {branch.Tip.Sha[..7]} {Markup.Escape(branch.Tip.Message)}"); } @@ -328,21 +509,22 @@ public static void OutputBranchAndStackActions( StackStatus stack, ILogger logger) { - if (stack.Branches.All(branch => branch.CouldBeCleanedUp)) + var allBranches = stack.GetAllBranches(); + if (allBranches.All(branch => branch.CouldBeCleanedUp)) { logger.Information("All branches exist locally but are either not in the remote repository or the pull request associated with the branch is no longer open. This stack might be able to be deleted."); logger.NewLine(); logger.Information($"Run {$"stack delete --stack \"{stack.Name}\"".Example()} to delete the stack if it's no longer needed."); logger.NewLine(); } - else if (stack.Branches.Any(branch => branch.CouldBeCleanedUp)) + else if (allBranches.Any(branch => branch.CouldBeCleanedUp)) { logger.Information("Some branches exist locally but are either not in the remote repository or the pull request associated with the branch is no longer open."); logger.NewLine(); logger.Information($"Run {$"stack cleanup --stack \"{stack.Name}\"".Example()} to clean up local branches."); logger.NewLine(); } - else if (stack.Branches.All(branch => !branch.Exists)) + else if (allBranches.All(branch => !branch.Exists)) { logger.Information("No branches exist locally. This stack might be able to be deleted."); logger.NewLine(); @@ -350,7 +532,7 @@ public static void OutputBranchAndStackActions( logger.NewLine(); } - if (stack.Branches.Any(branch => branch.Exists && (branch.RemoteTrackingBranch is null || branch.RemoteTrackingBranch.Ahead > 0))) + if (allBranches.Any(branch => branch.Exists && (branch.RemoteTrackingBranch is null || branch.RemoteTrackingBranch.Ahead > 0))) { logger.Information("There are changes in local branches that have not been pushed to the remote repository."); logger.NewLine(); @@ -358,7 +540,7 @@ public static void OutputBranchAndStackActions( logger.NewLine(); } - if (stack.Branches.Any(branch => branch.Exists && branch.RemoteTrackingBranch is not null && branch.RemoteTrackingBranch.Behind > 0)) + if (allBranches.Any(branch => branch.Exists && branch.RemoteTrackingBranch is not null && branch.RemoteTrackingBranch.Behind > 0)) { logger.Information("There are changes in source branches that have not been applied to the stack."); logger.NewLine(); @@ -429,19 +611,31 @@ public static void UpdateStackUsingMerge( IInputProvider inputProvider, ILogger logger) { - var sourceBranch = stack.SourceBranch; - foreach (var branch in status.Branches) { - if (branch.IsActive) - { - MergeFromSourceBranch(branch.Name, sourceBranch, gitClient, inputProvider, logger); - sourceBranch = branch.Name; - } - else - { - logger.Debug($"Branch '{branch}' no longer exists on the remote repository or the associated pull request is no longer open. Skipping..."); - } + UpdateBranchUsingMerge(branch, status.SourceBranch, gitClient, inputProvider, logger); + } + } + + public static void UpdateBranchUsingMerge( + BranchDetail branch, + BranchDetailBase parentBranch, + IGitClient gitClient, + IInputProvider inputProvider, + ILogger logger) + { + if (branch.IsActive) + { + MergeFromSourceBranch(branch.Name, parentBranch.Name, gitClient, inputProvider, logger); + } + else + { + logger.Debug($"Branch '{branch}' no longer exists on the remote repository or the associated pull request is no longer open. Skipping..."); + } + + foreach (var child in branch.Children) + { + UpdateBranchUsingMerge(child, branch.IsActive ? branch : parentBranch, gitClient, inputProvider, logger); } } @@ -629,16 +823,18 @@ public static void UpdateStackUsingRebase( // all commits from feature3 (and therefore from feature2) on top of the latest commits of main // which will include the squashed commit. // - string? branchToRebaseFrom = null; - string? lowestInactiveBranchToReParentFrom = null; - - foreach (var branch in status.Branches) + var lowestActionBranch = status.WalkBranches(b => { - if (branch.IsActive) + if (b.IsActive && b.Children.Count == 0) { - branchToRebaseFrom = branch.Name; + return WalkAction.Return; } - } + + return WalkAction.Continue; + }); + + string? branchToRebaseFrom = lowestActionBranch?.Name; + string? lowestInactiveBranchToReParentFrom = null; if (branchToRebaseFrom is null) { @@ -651,7 +847,7 @@ public static void UpdateStackUsingRebase( branchesToRebaseOnto.Remove(branchToRebaseFrom); branchesToRebaseOnto.Add(stack.SourceBranch); - List allBranchesInStack = [status.SourceBranch, .. status.Branches]; + List allBranchesInStack = [status.SourceBranch, .. status.GetAllBranches()]; foreach (var branchToRebaseOnto in branchesToRebaseOnto) { diff --git a/src/Stack/Commands/PullRequests/CreatePullRequestsCommand.cs b/src/Stack/Commands/PullRequests/CreatePullRequestsCommand.cs index 97d89a26..58e1072e 100644 --- a/src/Stack/Commands/PullRequests/CreatePullRequestsCommand.cs +++ b/src/Stack/Commands/PullRequests/CreatePullRequestsCommand.cs @@ -1,4 +1,5 @@ using System.ComponentModel; +using MoreLinq; using Spectre.Console; using Spectre.Console.Cli; using Stack.Commands.Helpers; @@ -92,7 +93,7 @@ public override async Task Handle(CreatePullRequestsCommandInputs inputs) } } - StackHelpers.OutputStackStatus(status, logger); + StackHelpers.OutputStackStatus(stackData.SchemaVersion, status, logger); logger.NewLine(); @@ -124,7 +125,7 @@ public override async Task Handle(CreatePullRequestsCommandInputs inputs) logger.NewLine(); - OutputUpdatedStackStatus(logger, stack, status, pullRequestInformation); + OutputUpdatedStackStatus(logger, stackData.SchemaVersion, stack, status, pullRequestInformation); logger.NewLine(); @@ -203,9 +204,9 @@ private static List CreatePullRequests( return pullRequests; } - private static void OutputUpdatedStackStatus(ILogger logger, Config.Stack stack, StackStatus status, List pullRequestCreateActions) + private static void OutputUpdatedStackStatus(ILogger logger, SchemaVersion schemaVersion, Config.Stack stack, StackStatus status, List pullRequestInformation) { - var branchDisplayItems = new List(); + var branchDisplayItems = new List>(); foreach (var branch in status.Branches) { @@ -215,21 +216,18 @@ private static void OutputUpdatedStackStatus(ILogger logger, Config.Stack stack, } else { - var action = pullRequestCreateActions.FirstOrDefault(a => a.HeadBranch == branch.Name); - if (action is not null) - { - branchDisplayItems.Add($"{StackHelpers.GetBranchStatusOutput(branch)} {$"*NEW* {action.Title}".Highlighted()}{(action.Draft == true ? " (draft)".Muted() : string.Empty)}"); - } - else - { - branchDisplayItems.Add(StackHelpers.GetBranchStatusOutput(branch)); - } + branchDisplayItems.Add(StackHelpers.GetBranchAndPullRequestInformation(branch, pullRequestInformation)); } } - logger.Tree( + if (schemaVersion == SchemaVersion.V1 && branchDisplayItems.Count > 0) + { + branchDisplayItems = [.. MoreEnumerable.TraverseDepthFirst(branchDisplayItems.First(), i => i.Children).Select(i => new TreeItem(i.Value, []))]; + } + + logger.Tree(new Tree( $"{stack.Name.Stack()}: {stack.SourceBranch.Muted()}", - [.. branchDisplayItems]); + [.. branchDisplayItems])); } private static List GetPullRequestInformation( @@ -291,7 +289,7 @@ private static List GetPullRequestInformation( return pullRequestActions; } - record PullRequestInformation( + public record PullRequestInformation( string HeadBranch, string BaseBranch, string Title, diff --git a/src/Stack/Commands/Remote/SyncStackCommand.cs b/src/Stack/Commands/Remote/SyncStackCommand.cs index be035552..e5e43c2a 100644 --- a/src/Stack/Commands/Remote/SyncStackCommand.cs +++ b/src/Stack/Commands/Remote/SyncStackCommand.cs @@ -105,7 +105,7 @@ public override async Task Handle(SyncStackCommandInputs inputs) gitHubClient, true); - StackHelpers.OutputStackStatus(status, logger); + StackHelpers.OutputStackStatus(stackData.SchemaVersion, status, logger); logger.NewLine(); diff --git a/src/Stack/Commands/Stack/StackStatusCommand.cs b/src/Stack/Commands/Stack/StackStatusCommand.cs index 0b37e92f..ab84d052 100644 --- a/src/Stack/Commands/Stack/StackStatusCommand.cs +++ b/src/Stack/Commands/Stack/StackStatusCommand.cs @@ -46,7 +46,8 @@ public record StackStatusCommandJsonOutputBranchDetail StackStatusCommandJsonOutputCommit? Tip, StackStatusCommandJsonOutputRemoteTrackingBranchStatus? RemoteTrackingBranch, StackStatusCommandJsonOutputGitHubPullRequest? PullRequest, - StackStatusCommandJsonOutputParentBranchStatus? Parent + StackStatusCommandJsonOutputParentBranchStatus? Parent, + List Children ) : StackStatusCommandJsonOutputBranch(Name, Exists, Tip, RemoteTrackingBranch); public record StackStatusCommandJsonOutputRemoteTrackingBranchStatus @@ -74,7 +75,7 @@ bool IsDraft public record StackStatusCommandJsonOutputParentBranchStatus ( - StackStatusCommandJsonOutputBranch Branch, + string Name, int Ahead, int Behind ); @@ -95,7 +96,7 @@ protected override async Task Execute(StackStatusCom protected override void WriteDefaultOutput(StackStatusCommandResponse response) { - StackHelpers.OutputStackStatus(response.Stacks, StdOutLogger); + StackHelpers.OutputStackStatus(response.SchemaVersion, response.Stacks, StdOutLogger); if (response.Stacks.Count == 1) { @@ -116,7 +117,7 @@ private static StackStatusCommandJsonOutput MapToJsonOutput(StackStatus stack) return new StackStatusCommandJsonOutput( stack.Name, MapBranch(stack.SourceBranch), - stack.Branches.Select(MapBranchDetail).ToList() + [.. stack.Branches.Select(MapBranchDetail)] ); } @@ -137,7 +138,7 @@ private static StackStatusCommandJsonOutputBranch MapBranch(BranchDetailBase bra private static StackStatusCommandJsonOutputBranchDetail MapBranchDetail(BranchDetail branch) { - return new StackStatusCommandJsonOutputBranchDetail( + var branchDetail = new StackStatusCommandJsonOutputBranchDetail( branch.Name, branch.Exists, branch.Tip is null ? null : new StackStatusCommandJsonOutputCommit(branch.Tip.Sha, branch.Tip.Message), @@ -155,16 +156,20 @@ private static StackStatusCommandJsonOutputBranchDetail MapBranchDetail(BranchDe branch.PullRequest.IsDraft ), branch.Parent is null ? null : new StackStatusCommandJsonOutputParentBranchStatus( - MapBranch(branch.Parent.Branch), + branch.Parent.Name, branch.Parent.Ahead, branch.Parent.Behind - ) + ), + [] ); + + branchDetail.Children.AddRange(branch.Children.Select(MapBranchDetail)); + return branchDetail; } } public record StackStatusCommandInputs(string? Stack, bool All, bool Full); -public record StackStatusCommandResponse(List Stacks); +public record StackStatusCommandResponse(SchemaVersion SchemaVersion, List Stacks); public class StackStatusCommandHandler( IInputProvider inputProvider, @@ -209,6 +214,6 @@ public override async Task Handle(StackStatusCommand gitHubClient, inputs.Full); - return new StackStatusCommandResponse(stackStatusResults); + return new StackStatusCommandResponse(stackData.SchemaVersion, stackStatusResults); } } \ No newline at end of file diff --git a/src/Stack/Infrastructure/ConsoleLogger.cs b/src/Stack/Infrastructure/ConsoleLogger.cs index bba40246..0d4bff4c 100644 --- a/src/Stack/Infrastructure/ConsoleLogger.cs +++ b/src/Stack/Infrastructure/ConsoleLogger.cs @@ -1,9 +1,11 @@ using Spectre.Console; +using Spectre.Console.Rendering; namespace Stack.Infrastructure; public interface ILogger { + void Tree(Tree tree); void Tree(string header, string[] items); void Status(string message, Action action); void Information(string message); @@ -47,8 +49,36 @@ public void Rule(string message) rule.DoubleBorder(); console.Write(rule); } + + public void Tree(Tree tree) + { + var consoleTree = new Tree(tree.Header); + foreach (var child in tree.Children) + { + var treeNode = consoleTree.AddNode(child.Value); + AddChildTreeNodes(treeNode, child); + } + + console.Write(consoleTree); + } + + void AddChildTreeNodes(TreeNode parent, TreeItem item) + { + foreach (var child in item.Children) + { + var node = parent.AddNode(child.Value); + if (child.Children.Count > 0) + { + AddChildTreeNodes(node, child); + } + } + } } +public record Tree(string Header, List> Children); + +public record TreeItem(T Value, List> Children); + public static class OutputStyleExtensionMethods { public static string Stack(this string name) => $"[{Color.Yellow}]{name}[/]"; diff --git a/src/Stack/Stack.csproj b/src/Stack/Stack.csproj index 8074425c..c6761669 100644 --- a/src/Stack/Stack.csproj +++ b/src/Stack/Stack.csproj @@ -14,6 +14,7 @@ +