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 return nil
} }
// RepositionStatus re-positions a status on the Kanban board. // RepositionStatus re-positions a Status value on a slice of Statuses.
func (b *Board) RepositionStatus(currentPosition, targetPosition int) error { func (b *Board) RepositionStatus(currentIndex, targetIndex int) error {
statuses, err := b.StatusList() statuses, err := b.StatusList()
if err != nil { if err != nil {
return fmt.Errorf("unable to get the list of statuses; %w", err) 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 { if err := b.normaliseStatusesPositionValues(statuses); err != nil {
return fmt.Errorf("unable to normalise the statuses position values; %w", err) return fmt.Errorf("unable to normalise the statuses position values; %w", err)

View file

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

View file

@ -2,6 +2,7 @@ package board_test
import ( import (
"errors" "errors"
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"reflect" "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 (Doing to In Progress)", testUpdateStatus(kanban, 2, 2, "In Progress"))
t.Run("Test Status Update (To Do to Backlog)", testUpdateStatus(kanban, 1, 1, "Backlog")) t.Run("Test Status Update (To Do to Backlog)", testUpdateStatus(kanban, 1, 1, "Backlog"))
// (TODO: Rearranging statuses still needs to be implemented) t.Logf("Our current column positioning is: Backlog, In Progress, Done, On Hold, Next.")
// Rearrange the board so the order is: Backlog, Next, In Progress, On Hold, Done 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.Logf("Let us now try moving a card from one status to another...")
t.Run("Test Move Card To Status", testMoveCardToStatus(kanban)) t.Run("Test Move Card To Status", testMoveCardToStatus(kanban))
// TODO: This needs to be updated when we re-arrange the board. expectedPositionsAfterDelete := map[int]string{
expectedPositions := map[int]string{
1: "Backlog", 1: "Backlog",
2: "In Progress", 2: "Next",
3: "Done", 3: "In Progress",
4: "Next", 4: "Done",
} }
t.Logf("Let us now delete the 'On Hold' status from the database...") 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.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) { 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) { func testRepositionStatuses(kanban board.Board, currentIndex, targetIndex int, wantPositions map[int]string) func(t *testing.T) {
// return 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) { func testMoveCardToStatus(kanban board.Board) func(t *testing.T) {
return 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 { 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) 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) t.Logf("\tVerifying that the card has moved to '%s'...", status2.Name)