2023-05-06 12:49:40 +01:00
|
|
|
package board_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
2023-12-12 14:42:45 +00:00
|
|
|
"time"
|
2023-05-06 12:49:40 +01:00
|
|
|
|
|
|
|
"codeflow.dananglin.me.uk/apollo/pelican/internal/board"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestCardLifecycle(t *testing.T) {
|
|
|
|
t.Log("Testing the lifecycle of a card.")
|
|
|
|
|
|
|
|
projectDir, err := projectRoot()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf(err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
testDBPath := filepath.Join(projectDir, "test", "databases", "Board_TestCardLifecycle.db")
|
|
|
|
os.Remove(testDBPath)
|
|
|
|
|
|
|
|
kanban, err := board.Open(testDBPath)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Unable to open the test Kanban board, %s.", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
_ = kanban.Close()
|
|
|
|
}()
|
|
|
|
|
|
|
|
initialCardTitle := "A test card."
|
|
|
|
initialCardContent := "Ensure that this card is safely stored in the database."
|
|
|
|
expectedCardID := 1
|
|
|
|
expectedStatusID := 1
|
2023-12-12 14:42:45 +00:00
|
|
|
timestamp := time.Now().Format(time.DateOnly)
|
2023-05-06 12:49:40 +01:00
|
|
|
|
|
|
|
t.Run("Test Create Card", testCreateCard(kanban, initialCardTitle, initialCardContent, expectedCardID, expectedStatusID))
|
|
|
|
|
2023-12-12 14:42:45 +00:00
|
|
|
t.Run("Test Read Card", testReadCard(kanban, expectedCardID, initialCardTitle, initialCardContent, timestamp))
|
2023-05-06 12:49:40 +01:00
|
|
|
|
|
|
|
modifiedCardTitle := "Test card updated."
|
|
|
|
modifiedCardContent1 := "Ensure that this card is safely updated in the database."
|
|
|
|
|
2023-12-12 14:42:45 +00:00
|
|
|
t.Run("Test Update Card", testUpdateCard(kanban, expectedCardID, modifiedCardTitle, modifiedCardContent1, timestamp))
|
2023-05-06 12:49:40 +01:00
|
|
|
|
|
|
|
modifiedCardContent2 := "Updated card content only."
|
|
|
|
|
2023-12-12 14:42:45 +00:00
|
|
|
t.Run("Test Update Card Content", testUpdateCardContent(kanban, expectedCardID, modifiedCardTitle, modifiedCardContent2, timestamp))
|
2023-05-06 12:49:40 +01:00
|
|
|
|
|
|
|
t.Run("Test Card Delete", testDeleteCard(kanban, expectedCardID, expectedStatusID))
|
|
|
|
}
|
|
|
|
|
|
|
|
func testCreateCard(kanban board.Board, title, content string, expectedCardID, expectedStatusID int) func(t *testing.T) {
|
|
|
|
return func(t *testing.T) {
|
|
|
|
t.Log("When the card is created and saved to the database.")
|
|
|
|
|
|
|
|
args := board.CardArgs{
|
|
|
|
NewTitle: title,
|
|
|
|
NewContent: content,
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := kanban.CreateCard(args); err != nil {
|
|
|
|
t.Fatalf("ERROR: Unable to create the test card, %s.", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Logf("\t\tVerifying that the card's ID is in the expected status...")
|
|
|
|
|
|
|
|
status, err := kanban.Status(expectedStatusID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("ERROR: Unable to read status '%d', %v", expectedStatusID, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
numCardIDs := len(status.CardIds)
|
|
|
|
|
|
|
|
if numCardIDs != 1 {
|
|
|
|
t.Fatalf("ERROR: Unexpected number of cards in status '%d', want: %d, got %d.", expectedStatusID, 1, numCardIDs)
|
|
|
|
}
|
|
|
|
|
|
|
|
if expectedCardID != status.CardIds[0] {
|
|
|
|
t.Errorf("%s\tUnexpected card ID found in the default status, want: %d, got %d.", failure, expectedCardID, status.CardIds[0])
|
|
|
|
} else {
|
|
|
|
t.Logf("%s\tExpected card ID found in the default status, got %d.", success, status.CardIds[0])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-12 14:42:45 +00:00
|
|
|
func testReadCard(kanban board.Board, cardID int, wantTitle, wantContent, wantTimestamp string) func(t *testing.T) {
|
2023-05-06 12:49:40 +01:00
|
|
|
return func(t *testing.T) {
|
|
|
|
t.Log("When a card is read from the database.")
|
|
|
|
|
|
|
|
card, err := kanban.Card(cardID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("ERROR: Unable to read test card, %s.", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if card.Title != wantTitle {
|
|
|
|
t.Errorf("%s\tUnexpected card title received, want: %s, got: %s.", failure, wantTitle, card.Title)
|
|
|
|
} else {
|
|
|
|
t.Logf("%s\tExpected card title received, got: %s.", success, card.Title)
|
|
|
|
}
|
|
|
|
|
|
|
|
if card.Content != wantContent {
|
|
|
|
t.Errorf("%s\tUnexpected card content received, want: %s, got: %s.", failure, wantContent, card.Content)
|
|
|
|
} else {
|
|
|
|
t.Logf("%s\tExpected card content received, got: %s.", success, card.Content)
|
|
|
|
}
|
2023-12-12 14:42:45 +00:00
|
|
|
|
|
|
|
if card.Created != wantTimestamp {
|
|
|
|
t.Errorf("%s\tUnexpected timestamp received for the created card, want: %s, got %s.", failure, wantTimestamp, card.Created)
|
|
|
|
} else {
|
|
|
|
t.Logf("%s\tExpected timestamp received for the created card, got: %s.", success, card.Created)
|
|
|
|
}
|
2023-05-06 12:49:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-12 14:42:45 +00:00
|
|
|
func testUpdateCard(kanban board.Board, cardID int, newTitle, newContent, timestamp string) func(t *testing.T) {
|
2023-05-06 12:49:40 +01:00
|
|
|
return func(t *testing.T) {
|
|
|
|
t.Log("When a card is updated in the database.")
|
|
|
|
|
|
|
|
args := board.UpdateCardArgs{
|
|
|
|
CardID: cardID,
|
|
|
|
CardArgs: board.CardArgs{
|
|
|
|
NewTitle: newTitle,
|
|
|
|
NewContent: newContent,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := kanban.UpdateCard(args); err != nil {
|
|
|
|
t.Fatalf("ERROR: Unable to update the test card, %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
got, err := kanban.Card(cardID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("ERROR: Unable to read the modified test card, %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
want := board.Card{
|
|
|
|
ID: cardID,
|
|
|
|
Title: newTitle,
|
|
|
|
Content: newContent,
|
2023-12-12 14:52:03 +00:00
|
|
|
Created: timestamp,
|
2023-05-06 12:49:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Errorf("%s\tUnexpected card read from the database: want %+v, got %+v", failure, want, got)
|
|
|
|
} else {
|
|
|
|
t.Logf("%s\tExpected card read from the database: got %+v", success, got)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-12 14:42:45 +00:00
|
|
|
func testUpdateCardContent(kanban board.Board, cardID int, expectedTitle, newContent, timestamp string) func(t *testing.T) {
|
2023-05-06 12:49:40 +01:00
|
|
|
return func(t *testing.T) {
|
|
|
|
t.Log("When (and only when) a card's content is updated in the database.")
|
|
|
|
|
|
|
|
args := board.UpdateCardArgs{
|
|
|
|
CardID: cardID,
|
|
|
|
CardArgs: board.CardArgs{
|
|
|
|
NewTitle: "",
|
|
|
|
NewContent: newContent,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := kanban.UpdateCard(args); err != nil {
|
|
|
|
t.Fatalf("ERROR: Unable to update the test card, %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
got, err := kanban.Card(cardID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("ERROR: Unable to read the modified test card, %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
want := board.Card{
|
|
|
|
ID: cardID,
|
|
|
|
Title: expectedTitle,
|
|
|
|
Content: newContent,
|
2023-12-12 14:52:03 +00:00
|
|
|
Created: timestamp,
|
2023-05-06 12:49:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Errorf("%s\tUnexpected card read from the database, want: %+v, got: %+v", failure, want, got)
|
|
|
|
} else {
|
|
|
|
t.Logf("%s\tExpected card read from the database, got: %+v", success, got)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func testDeleteCard(kanban board.Board, cardID, statusID int) func(t *testing.T) {
|
|
|
|
return func(t *testing.T) {
|
|
|
|
t.Log("When deleting a card from the database.")
|
|
|
|
|
|
|
|
args := board.DeleteCardArgs{
|
|
|
|
CardID: cardID,
|
|
|
|
StatusID: statusID,
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := kanban.DeleteCard(args); err != nil {
|
|
|
|
t.Fatalf("ERROR: An error occurred when deleting the card from the database, %v", err)
|
|
|
|
} else {
|
|
|
|
t.Logf("%s\tNo errors occurred when deleting the card from the database.", success)
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Logf("\tVerifying that the card is removed from the database...")
|
|
|
|
|
|
|
|
_, err := kanban.Card(cardID)
|
|
|
|
if err == nil {
|
|
|
|
t.Errorf("%s\tDid not receive the expected error when attempting to read the deleted card.", failure)
|
|
|
|
} else {
|
|
|
|
if errors.Is(err, board.CardNotExistError{}) {
|
|
|
|
t.Errorf(
|
|
|
|
"%s\tDid not receive the expected board.CardNotExistError when attempting to retrieve the deleted card, instead got '%v'.",
|
|
|
|
failure,
|
|
|
|
err,
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
t.Logf("%s\tSuccessfully received board.CardNotExistError when attempting to retrieve the deleted card.", success)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Logf("\tVerifying that the card's ID is removed from the status list...")
|
|
|
|
|
|
|
|
status, err := kanban.Status(statusID)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("ERROR: Unable to read status '%d' from the database; %v", statusID, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
numCardIDs := len(status.CardIds)
|
|
|
|
if numCardIDs != 0 {
|
|
|
|
t.Errorf("%s\tUnexpected non-empty list of card IDs in status '%d', got '%+v' card IDs.", failure, statusID, status.CardIds)
|
|
|
|
} else {
|
|
|
|
t.Logf("%s\tThe card ID was successfully removed from the list of card in status '%d'.", success, statusID)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|