added test cases for column repositioning
This commit is contained in:
parent
4286d8fcc2
commit
68dcdae56d
3 changed files with 88 additions and 24 deletions
|
@ -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)
|
||||||
|
|
|
@ -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]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue