added test cases for column repositioning
All checks were successful
/ test (pull_request) Successful in 34s
/ lint (pull_request) Successful in 35s

This commit is contained in:
Dan Anglin 2024-01-24 01:09:56 +00:00
parent 4286d8fcc2
commit 68dcdae56d
Signed by: dananglin
GPG key ID: 0C1D44CFBEE68638
3 changed files with 88 additions and 24 deletions

View file

@ -205,14 +205,14 @@ func (b *Board) DeleteStatus(statusID int) error {
return nil
}
// RepositionStatus re-positions a status on the Kanban board.
func (b *Board) RepositionStatus(currentPosition, targetPosition int) error {
// RepositionStatus re-positions a Status value on a slice of Statuses.
func (b *Board) RepositionStatus(currentIndex, targetIndex int) error {
statuses, err := b.StatusList()
if err != nil {
return fmt.Errorf("unable to get the list of statuses; %w", err)
}
statuses = moveAndShuffle(statuses, currentPosition, targetPosition)
statuses = moveAndShuffle(statuses, currentIndex, targetIndex)
if err := b.normaliseStatusesPositionValues(statuses); err != nil {
return fmt.Errorf("unable to normalise the statuses position values; %w", err)

View file

@ -13,10 +13,10 @@ const (
// direction of the move.
// This is currently used to move specified columns forwards or backwards on the Kanban board.
// When a column changes position the other columns shuffle forward or backwards as required.
func moveAndShuffle(input []Status, currentPosition, targetPosition int) []Status {
func moveAndShuffle(input []Status, currentIndex, targetIndex int) []Status {
var shuffle shuffleDirection
if targetPosition < currentPosition {
if targetIndex < currentIndex {
// affected elements will need to shuffle backwards if the focused
// element moves towards the beginning of the list...
shuffle = backwards
@ -30,16 +30,16 @@ func moveAndShuffle(input []Status, currentPosition, targetPosition int) []Statu
for ind := range input {
switch {
case (shuffle == backwards) && (ind < targetPosition || ind > currentPosition):
case (shuffle == backwards) && (ind < targetIndex || ind > currentIndex):
output[ind] = input[ind]
case (shuffle == backwards) && (ind == currentPosition):
output[targetPosition] = input[ind]
case (shuffle == backwards) && (ind == currentIndex):
output[targetIndex] = input[ind]
case (shuffle == backwards):
output[ind+1] = input[ind]
case (shuffle == forwards) && (ind < currentPosition || ind > targetPosition):
case (shuffle == forwards) && (ind < currentIndex || ind > targetIndex):
output[ind] = input[ind]
case (shuffle == forwards) && (ind == currentPosition):
output[targetPosition] = input[ind]
case (shuffle == forwards) && (ind == currentIndex):
output[targetIndex] = input[ind]
case (shuffle == forwards):
output[ind-1] = input[ind]
}

View file

@ -2,6 +2,7 @@ package board_test
import (
"errors"
"fmt"
"os"
"path/filepath"
"reflect"
@ -57,25 +58,65 @@ func TestStatusLifecycle(t *testing.T) {
t.Run("Test Status Update (Doing to In Progress)", testUpdateStatus(kanban, 2, 2, "In Progress"))
t.Run("Test Status Update (To Do to Backlog)", testUpdateStatus(kanban, 1, 1, "Backlog"))
// (TODO: Rearranging statuses still needs to be implemented)
// Rearrange the board so the order is: Backlog, Next, In Progress, On Hold, Done
t.Logf("Our current column positioning is: Backlog, In Progress, Done, On Hold, Next.")
t.Logf("Let us rearrange the board so that the order is: Backlog, Next, In Progress, On Hold, Done...")
// NOTE: the statuses current index is the index in the slice that is received from the database.
// The wantPositions is used to evaluate each statuses Position value after all the reshuffling and renormalisation.
rearrangeCases := []struct {
statusName string
currentIndex int
targetIndex int
wantPositions map[int]string
}{
{
statusName: "Done",
currentIndex: 2,
targetIndex: 4,
wantPositions: map[int]string{
1: "Backlog",
2: "In Progress",
3: "On Hold",
4: "Next",
5: "Done",
},
},
{
statusName: "Next",
currentIndex: 3,
targetIndex: 1,
wantPositions: map[int]string{
1: "Backlog",
2: "Next",
3: "In Progress",
4: "On Hold",
5: "Done",
},
},
}
for i := range rearrangeCases {
t.Run(
fmt.Sprintf("Test Re-Arrange Status: %s", rearrangeCases[i].statusName),
testRepositionStatuses(kanban, rearrangeCases[i].currentIndex, rearrangeCases[i].targetIndex, rearrangeCases[i].wantPositions),
)
}
t.Logf("Let us now try moving a card from one status to another...")
t.Run("Test Move Card To Status", testMoveCardToStatus(kanban))
// TODO: This needs to be updated when we re-arrange the board.
expectedPositions := map[int]string{
expectedPositionsAfterDelete := map[int]string{
1: "Backlog",
2: "In Progress",
3: "Done",
4: "Next",
2: "Next",
3: "In Progress",
4: "Done",
}
t.Logf("Let us now delete the 'On Hold' status from the database...")
t.Run("Test Delete Status (On Hold)", testDeleteEmptyStatus(kanban, statusOnHoldExpectedID, expectedPositions))
t.Run("Test Delete Status (On Hold)", testDeleteEmptyStatus(kanban, statusOnHoldExpectedID, expectedPositionsAfterDelete))
t.Logf("Additionally, let us try to delete a status that contains a card...")
t.Run("Test Delete a non-empty status", testDeleteNonEmptyStatus(kanban, 3))
t.Run("Test Delete a non-empty status", testDeleteNonEmptyStatus(kanban, 2))
}
func testCreateStatus(kanban board.Board, name string, position int) func(t *testing.T) {
@ -157,10 +198,31 @@ func testUpdateStatus(kanban board.Board, statusID, expectedPosition int, newNam
}
}
// func testRearrangeBoard() func(t *testing.T) {
// return func(t *testing.T) {
// }
// }
func testRepositionStatuses(kanban board.Board, currentIndex, targetIndex int, wantPositions map[int]string) func(t *testing.T) {
return func(t *testing.T) {
t.Logf("When repositioning a status on the board.")
if err := kanban.RepositionStatus(currentIndex, targetIndex); err != nil {
t.Fatalf("ERROR: Unable to reposition the status; %v", err)
}
statuses, err := kanban.StatusList()
if err != nil {
t.Fatalf("ERROR: an error was received when attempting to get the list of statuses from the database; %v", err)
}
gotPositions := make(map[int]string)
for _, status := range statuses {
gotPositions[status.Position] = status.Name
}
if !reflect.DeepEqual(wantPositions, gotPositions) {
t.Errorf("%s\tUnexpected positions received from the database; want: %v, got %v", failure, wantPositions, gotPositions)
} else {
t.Logf("%s\tExpected positions received from the database; got %v", success, gotPositions)
}
}
}
func testMoveCardToStatus(kanban board.Board) func(t *testing.T) {
return func(t *testing.T) {
@ -186,6 +248,8 @@ func testMoveCardToStatus(kanban board.Board) func(t *testing.T) {
if err := kanban.MoveToStatus(moveArgs); err != nil {
t.Fatalf("ERROR: Unable to move the Card ID from '%s' to '%s', %v", status0.Name, status2.Name, err)
} else {
t.Logf("%s\tThe MoveToStatus operation has completed without error.", success)
}
t.Logf("\tVerifying that the card has moved to '%s'...", status2.Name)