Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ Once you've done some work on the first branch within the stack, at some point y
- Give the branch a name.
- Select the branch to create the new branch from.

The new branch will be created from the branch at the bottom of the stack and the current branch will be changed so you can make more changes.
The new branch will be created from the selected parent branch and the current branch will be changed so you can make more changes.

If a new branch was not able to be pushed to the remote, you can use the `stack push` command to push the branch to the remote later.

Expand Down
125 changes: 23 additions & 102 deletions src/Stack.Tests/Commands/Branch/AddBranchCommandHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,41 +13,46 @@ namespace Stack.Tests.Commands.Branch;
public class AddBranchCommandHandlerTests(ITestOutputHelper testOutputHelper)
{
[Fact]
public async Task WhenNoInputsProvided_AsksForStackAndBranchAndConfirms_AddsBranchToStack()
public async Task WhenNoInputsProvided_AsksForStackAndBranchAndParentBranchAndConfirms_AddsBranchToStack()
{
// Arrange
var sourceBranch = Some.BranchName();
var anotherBranch = Some.BranchName();
var firstBranch = Some.BranchName();
var childBranch = Some.BranchName();
var branchToAdd = Some.BranchName();
var remoteUri = Some.HttpsUri().ToString();

var stackConfig = new TestStackConfigBuilder()
.WithStack(stack => stack
.WithName("Stack1")
.WithRemoteUri(remoteUri)
.WithSourceBranch(sourceBranch)
.WithBranch(branch => branch.WithName(anotherBranch)))
.WithStack(stack => stack.WithName("Stack2").WithRemoteUri(remoteUri).WithSourceBranch(sourceBranch))
.Build();
var inputProvider = Substitute.For<IInputProvider>();
var logger = new TestLogger(testOutputHelper);
var gitClient = Substitute.For<IGitClient>();
gitClient.GetRemoteUri().Returns(remoteUri);
gitClient.GetCurrentBranch().Returns(sourceBranch);
gitClient.GetLocalBranchesOrderedByMostRecentCommitterDate().Returns(new[] { sourceBranch, anotherBranch, branchToAdd });
gitClient.GetLocalBranchesOrderedByMostRecentCommitterDate().Returns(new[] { sourceBranch, firstBranch, childBranch, branchToAdd });
gitClient.DoesLocalBranchExist(branchToAdd).Returns(true);
var stackConfig = new TestStackConfigBuilder()
.WithStack(stack => stack
.WithName("Stack1")
.WithRemoteUri(remoteUri)
.WithSourceBranch(sourceBranch)
.WithBranch(branch => branch.WithName(firstBranch).WithChildBranch(child => child.WithName(childBranch))))
.WithStack(stack => stack
.WithName("Stack2")
.WithRemoteUri(remoteUri)
.WithSourceBranch(sourceBranch))
.Build();
var handler = new AddBranchCommandHandler(inputProvider, logger, gitClient, stackConfig);

inputProvider.Select(Questions.SelectStack, Arg.Any<string[]>()).Returns("Stack1");
inputProvider.Select(Questions.SelectBranch, Arg.Any<string[]>()).Returns(branchToAdd);
inputProvider.Select(Questions.SelectParentBranch, Arg.Any<string[]>()).Returns(firstBranch);

// Act
await handler.Handle(AddBranchCommandInputs.Empty);
await handler.Handle(new AddBranchCommandInputs(null, null, null));

// Assert
stackConfig.Stacks.Should().BeEquivalentTo(new List<Config.Stack>
{
new("Stack1", remoteUri, sourceBranch, [new Config.Branch(anotherBranch, [new Config.Branch(branchToAdd, [])])]),
new("Stack1", remoteUri, sourceBranch, [new Config.Branch(firstBranch, [new Config.Branch(childBranch, []), new Config.Branch(branchToAdd, [])])]),
new("Stack2", remoteUri, sourceBranch, [])
});
}
Expand Down Expand Up @@ -79,6 +84,7 @@ public async Task WhenStackNameProvided_DoesNotAskForStackName_AddsBranchFromSta
var handler = new AddBranchCommandHandler(inputProvider, logger, gitClient, stackConfig);

inputProvider.Select(Questions.SelectBranch, Arg.Any<string[]>()).Returns(branchToAdd);
inputProvider.Select(Questions.SelectParentBranch, Arg.Any<string[]>()).Returns(anotherBranch);

// Act
await handler.Handle(new AddBranchCommandInputs("Stack1", null, null));
Expand Down Expand Up @@ -118,6 +124,7 @@ public async Task WhenOnlyOneStackExists_DoesNotAskForStackName_AddsBranchFromSt
var handler = new AddBranchCommandHandler(inputProvider, logger, gitClient, stackConfig);

inputProvider.Select(Questions.SelectBranch, Arg.Any<string[]>()).Returns(branchToAdd);
inputProvider.Select(Questions.SelectParentBranch, Arg.Any<string[]>()).Returns(anotherBranch);

// Act
await handler.Handle(new AddBranchCommandInputs(null, null, null));
Expand Down Expand Up @@ -191,6 +198,7 @@ public async Task WhenBranchNameProvided_DoesNotAskForBranchName_AddsBranchFromS
var handler = new AddBranchCommandHandler(inputProvider, logger, gitClient, stackConfig);

inputProvider.Select(Questions.SelectStack, Arg.Any<string[]>()).Returns("Stack1");
inputProvider.Select(Questions.SelectParentBranch, Arg.Any<string[]>()).Returns(anotherBranch);

// Act
await handler.Handle(new AddBranchCommandInputs(null, branchToAdd, null));
Expand Down Expand Up @@ -305,7 +313,7 @@ public async Task WhenAllInputsProvided_DoesNotAskForAnything_AddsBranchFromStac
var handler = new AddBranchCommandHandler(inputProvider, logger, gitClient, stackConfig);

// Act
await handler.Handle(new AddBranchCommandInputs("Stack1", branchToAdd, null));
await handler.Handle(new AddBranchCommandInputs("Stack1", branchToAdd, anotherBranch));

// Assert
stackConfig.Stacks.Should().BeEquivalentTo(new List<Config.Stack>
Expand All @@ -317,7 +325,7 @@ public async Task WhenAllInputsProvided_DoesNotAskForAnything_AddsBranchFromStac
}

[Fact]
public async Task WhenV2Schema_AndParentBranchNotProvided_AsksForParentBranch_CreatesNewBranchUnderneathParent()
public async Task WhenParentBranchProvided_DoesNotAskForParentBranch_CreatesNewBranchUnderneathParent()
{
// Arrange
var sourceBranch = Some.BranchName();
Expand All @@ -334,53 +342,6 @@ public async Task WhenV2Schema_AndParentBranchNotProvided_AsksForParentBranch_Cr
gitClient.GetLocalBranchesOrderedByMostRecentCommitterDate().Returns(new[] { sourceBranch, firstBranch, childBranch, branchToAdd });
gitClient.DoesLocalBranchExist(branchToAdd).Returns(true);
var stackConfig = new TestStackConfigBuilder()
.WithSchemaVersion(SchemaVersion.V2)
.WithStack(stack => stack
.WithName("Stack1")
.WithRemoteUri(remoteUri)
.WithSourceBranch(sourceBranch)
.WithBranch(branch => branch.WithName(firstBranch).WithChildBranch(child => child.WithName(childBranch))))
.WithStack(stack => stack
.WithName("Stack2")
.WithRemoteUri(remoteUri)
.WithSourceBranch(sourceBranch))
.Build();
var handler = new AddBranchCommandHandler(inputProvider, logger, gitClient, stackConfig);

inputProvider.Select(Questions.SelectStack, Arg.Any<string[]>()).Returns("Stack1");
inputProvider.Select(Questions.SelectBranch, Arg.Any<string[]>()).Returns(branchToAdd);
inputProvider.Select(Questions.SelectParentBranch, Arg.Any<string[]>()).Returns(firstBranch);

// Act
await handler.Handle(new AddBranchCommandInputs(null, null, null));

// Assert
stackConfig.Stacks.Should().BeEquivalentTo(new List<Config.Stack>
{
new("Stack1", remoteUri, sourceBranch, [new Config.Branch(firstBranch, [new Config.Branch(childBranch, []), new Config.Branch(branchToAdd, [])])]),
new("Stack2", remoteUri, sourceBranch, [])
});
}

[Fact]
public async Task WhenV2Schema_AndParentBranchProvided_DoesNotAskForParentBranch_CreatesNewBranchUnderneathParent()
{
// Arrange
var sourceBranch = Some.BranchName();
var firstBranch = Some.BranchName();
var childBranch = Some.BranchName();
var branchToAdd = Some.BranchName();
var remoteUri = Some.HttpsUri().ToString();

var inputProvider = Substitute.For<IInputProvider>();
var logger = new TestLogger(testOutputHelper);
var gitClient = Substitute.For<IGitClient>();
gitClient.GetRemoteUri().Returns(remoteUri);
gitClient.GetCurrentBranch().Returns(sourceBranch);
gitClient.GetLocalBranchesOrderedByMostRecentCommitterDate().Returns(new[] { sourceBranch, firstBranch, childBranch, branchToAdd });
gitClient.DoesLocalBranchExist(branchToAdd).Returns(true);
var stackConfig = new TestStackConfigBuilder()
.WithSchemaVersion(SchemaVersion.V2)
.WithStack(stack => stack
.WithName("Stack1")
.WithRemoteUri(remoteUri)
Expand Down Expand Up @@ -408,44 +369,4 @@ public async Task WhenV2Schema_AndParentBranchProvided_DoesNotAskForParentBranch

inputProvider.DidNotReceive().Select(Questions.SelectParentBranch, Arg.Any<string[]>());
}

[Fact]
public async Task WhenV1Schema_AndParentBranchProvided_ThrowsException()
{
// Arrange
var sourceBranch = Some.BranchName();
var firstBranch = Some.BranchName();
var childBranch = Some.BranchName();
var branchToAdd = Some.BranchName();
var remoteUri = Some.HttpsUri().ToString();

var inputProvider = Substitute.For<IInputProvider>();
var logger = new TestLogger(testOutputHelper);
var gitClient = Substitute.For<IGitClient>();
gitClient.GetRemoteUri().Returns(remoteUri);
gitClient.GetCurrentBranch().Returns(sourceBranch);
gitClient.GetLocalBranchesOrderedByMostRecentCommitterDate().Returns(new[] { sourceBranch, firstBranch, childBranch, branchToAdd });
gitClient.DoesLocalBranchExist(branchToAdd).Returns(true);
var stackConfig = new TestStackConfigBuilder()
.WithSchemaVersion(SchemaVersion.V1)
.WithStack(stack => stack
.WithName("Stack1")
.WithRemoteUri(remoteUri)
.WithSourceBranch(sourceBranch)
.WithBranch(branch => branch.WithName(firstBranch).WithChildBranch(child => child.WithName(childBranch))))
.WithStack(stack => stack
.WithName("Stack2")
.WithRemoteUri(remoteUri)
.WithSourceBranch(sourceBranch))
.Build();
var handler = new AddBranchCommandHandler(inputProvider, logger, gitClient, stackConfig);

inputProvider.Select(Questions.SelectStack, Arg.Any<string[]>()).Returns("Stack1");
inputProvider.Select(Questions.SelectBranch, Arg.Any<string[]>()).Returns(branchToAdd);

// Act and assert
await handler.Invoking(h => h.Handle(new AddBranchCommandInputs(null, null, firstBranch)))
.Should().ThrowAsync<InvalidOperationException>()
.WithMessage("Parent branches are not supported in stacks with schema version v1. Please migrate the stack to v2 format.");
}
}
Loading
Loading