From 911f13c8d679241859bf31319a370faad5cb2db6 Mon Sep 17 00:00:00 2001 From: Yasuyuki Takeo Date: Sun, 14 Jul 2024 07:14:57 +0900 Subject: [PATCH] Fix tests --- backend/graph/schema.resolvers.go | 20 ++- backend/graph/schema.resolvers_test.go | 162 ++++++++++++++---- backend/pkg/flashcard/flashcard_system.go | 2 +- .../pkg/flashcard/flashcard_system_test.go | 12 +- backend/pkg/model/model.go | 40 ++--- 5 files changed, 167 insertions(+), 69 deletions(-) diff --git a/backend/graph/schema.resolvers.go b/backend/graph/schema.resolvers.go index fc2306b..3ef170e 100644 --- a/backend/graph/schema.resolvers.go +++ b/backend/graph/schema.resolvers.go @@ -1,5 +1,9 @@ package graph +// This file will be automatically regenerated based on the schema, any resolver implementations +// will be copied through when generating and any unknown code will be moved to the end. +// Code generated by github.com/99designs/gqlgen version v0.17.49 + import ( "backend/graph/model" repository "backend/pkg/model" @@ -80,7 +84,7 @@ func (r *mutationResolver) CreateCardGroup(ctx context.Context, input model.NewC // UpdateCardGroup is the resolver for the updateCardGroup field. func (r *mutationResolver) UpdateCardGroup(ctx context.Context, id int64, input model.NewCardGroup) (*model.CardGroup, error) { - var cardGroup repository.CardGroup + var cardGroup repository.Cardgroup if err := r.DB.First(&cardGroup, id).Error; err != nil { return nil, err } @@ -99,7 +103,7 @@ func (r *mutationResolver) UpdateCardGroup(ctx context.Context, id int64, input // DeleteCardGroup is the resolver for the deleteCardGroup field. func (r *mutationResolver) DeleteCardGroup(ctx context.Context, id int64) (bool, error) { - if err := r.DB.Delete(&repository.CardGroup{}, id).Error; err != nil { + if err := r.DB.Delete(&repository.Cardgroup{}, id).Error; err != nil { return false, err } return true, nil @@ -187,7 +191,7 @@ func (r *mutationResolver) DeleteRole(ctx context.Context, id int64) (bool, erro // AddUserToCardGroup is the resolver for the addUserToCardGroup field. func (r *mutationResolver) AddUserToCardGroup(ctx context.Context, userID int64, cardGroupID int64) (*model.CardGroup, error) { var user repository.User - var cardGroup repository.CardGroup + var cardGroup repository.Cardgroup if err := r.DB.First(&user, userID).Error; err != nil { return nil, err } @@ -208,7 +212,7 @@ func (r *mutationResolver) AddUserToCardGroup(ctx context.Context, userID int64, // RemoveUserFromCardGroup is the resolver for the removeUserFromCardGroup field. func (r *mutationResolver) RemoveUserFromCardGroup(ctx context.Context, userID int64, cardGroupID int64) (*model.CardGroup, error) { var user repository.User - var cardGroup repository.CardGroup + var cardGroup repository.Cardgroup if err := r.DB.First(&user, userID).Error; err != nil { return nil, err } @@ -308,7 +312,7 @@ func (r *queryResolver) Card(ctx context.Context, id int64) (*model.Card, error) // CardGroups is the resolver for the cardGroups field. func (r *queryResolver) CardGroups(ctx context.Context) ([]*model.CardGroup, error) { - var cardGroups []repository.CardGroup + var cardGroups []repository.Cardgroup if err := r.DB.Find(&cardGroups).Error; err != nil { return nil, err } @@ -326,7 +330,7 @@ func (r *queryResolver) CardGroups(ctx context.Context) ([]*model.CardGroup, err // CardGroup is the resolver for the cardGroup field. func (r *queryResolver) CardGroup(ctx context.Context, id int64) (*model.CardGroup, error) { - var cardGroup repository.CardGroup + var cardGroup repository.Cardgroup if err := r.DB.First(&cardGroup, id).Error; err != nil { return nil, err } @@ -429,8 +433,8 @@ func convertToGormCard(input model.NewCard) repository.Card { Updated: time.Now(), } } -func convertToGormCardGroup(input model.NewCardGroup) repository.CardGroup { - return repository.CardGroup{ +func convertToGormCardGroup(input model.NewCardGroup) repository.Cardgroup { + return repository.Cardgroup{ Name: input.Name, Created: time.Now(), Updated: time.Now(), diff --git a/backend/graph/schema.resolvers_test.go b/backend/graph/schema.resolvers_test.go index 97cf7cf..1b259a5 100644 --- a/backend/graph/schema.resolvers_test.go +++ b/backend/graph/schema.resolvers_test.go @@ -8,6 +8,7 @@ import ( "log" "net/http" "net/http/httptest" + "strings" "testing" "time" @@ -73,23 +74,69 @@ func setupEchoServer(db *gorm.DB) *echo.Echo { return e } -func testGraphQLQuery(t *testing.T, e *echo.Echo, jsonInput []byte, expected string) { +func testGraphQLQuery(t *testing.T, e *echo.Echo, jsonInput []byte, expected string, ignoreFields ...string) { req := httptest.NewRequest(http.MethodPost, "/query", bytes.NewBuffer(jsonInput)) req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() e.ServeHTTP(rec, req) - assert.JSONEq(t, expected, rec.Body.String()) + var actualResponse map[string]interface{} + var expectedResponse map[string]interface{} + + // Parse the actual response + if err := json.Unmarshal(rec.Body.Bytes(), &actualResponse); err != nil { + t.Fatalf("Failed to unmarshal actual response: %v", err) + } + + // Parse the expected response + if err := json.Unmarshal([]byte(expected), &expectedResponse); err != nil { + t.Fatalf("Failed to unmarshal expected response: %v", err) + } + + // Remove the fields to ignore from both responses + for _, field := range ignoreFields { + removeField(actualResponse, field) + removeField(expectedResponse, field) + } + + // Compare the modified responses + assert.Equal(t, expectedResponse, actualResponse) +} + +func removeField(data map[string]interface{}, field string) { + // Split the field into parts if it's nested (e.g., data.createCard.created) + parts := strings.Split(field, ".") + current := data + + for i, part := range parts { + if i == len(parts)-1 { + delete(current, part) + } else if next, ok := current[part].(map[string]interface{}); ok { + current = next + } else { + break + } + } } func TestMutationResolver_CreateCard(t *testing.T) { + // Step 1: Create a Cardgroup + now := time.Now() + cardgroup := repository.Cardgroup{ + Name: "Test Cardgroup", + Created: now, + Updated: now, + } + db.Create(&cardgroup) + + // Step 2: Create a new card with the CardgroupID input := model.NewCard{ Front: "Front of card", Back: "Back of card", - ReviewDate: time.Now(), + ReviewDate: now, IntervalDays: new(int), - CardgroupID: 1, + CardgroupID: cardgroup.ID, } jsonInput, _ := json.Marshal(map[string]interface{}{ "query": `mutation ($input: NewCard!) { @@ -107,25 +154,40 @@ func TestMutationResolver_CreateCard(t *testing.T) { "input": input, }, }) - expected := `{ + expected := fmt.Sprintf(`{ "data": { "createCard": { "front": "Front of card", - "back": "Back of card" + "back": "Back of card", + "review_date": "%s", + "interval_days": 1, + "created": "%s", + "updated": "%s", + "id": 1 } } - }` - testGraphQLQuery(t, e, jsonInput, expected) + }`, cardgroup.Created.Format(time.RFC3339Nano), cardgroup.Created.Format(time.RFC3339Nano), cardgroup.Updated.Format(time.RFC3339Nano)) + + testGraphQLQuery(t, e, jsonInput, expected, "data.createCard.created", "data.createCard.updated") } func TestMutationResolver_UpdateCard(t *testing.T) { + // Step 1: Create a Cardgroup + now := time.Now() + cardgroup := repository.Cardgroup{ + Name: "Test Cardgroup", + Created: now, + Updated: now, + } + db.Create(&cardgroup) + // Create a card to update card := repository.Card{ Front: "Old Front", Back: "Old Back", ReviewDate: time.Now(), IntervalDays: 1, - CardGroupID: 1, + CardGroupID: cardgroup.ID, Created: time.Now(), Updated: time.Now(), } @@ -137,7 +199,7 @@ func TestMutationResolver_UpdateCard(t *testing.T) { ReviewDate: time.Now(), } jsonInput, _ := json.Marshal(map[string]interface{}{ - "query": `mutation ($id: Int!, $input: NewCard!) { + "query": `mutation ($id: ID!, $input: NewCard!) { updateCard(id: $id, input: $input) { id front @@ -162,24 +224,33 @@ func TestMutationResolver_UpdateCard(t *testing.T) { } } }` - testGraphQLQuery(t, e, jsonInput, expected) + testGraphQLQuery(t, e, jsonInput, expected, "data.updateCard.created", "data.updateCard.updated", "data.updateCard.review_date", "data.updateCard.interval_days") } func TestMutationResolver_DeleteCard(t *testing.T) { - // Create a card to delete + // Step 1: Create a Cardgroup + now := time.Now() + cardgroup := repository.Cardgroup{ + Name: "Test Cardgroup", + Created: now, + Updated: now, + } + db.Create(&cardgroup) + + // Step 2: Create a card to delete card := repository.Card{ Front: "Front to delete", Back: "Back to delete", ReviewDate: time.Now(), IntervalDays: 1, - CardGroupID: 1, + CardGroupID: cardgroup.ID, // Ensure this matches the created cardgroup Created: time.Now(), Updated: time.Now(), } db.Create(&card) jsonInput, _ := json.Marshal(map[string]interface{}{ - "query": `mutation ($id: Int!) { + "query": `mutation ($id: ID!) { deleteCard(id: $id) }`, "variables": map[string]interface{}{ @@ -195,17 +266,28 @@ func TestMutationResolver_DeleteCard(t *testing.T) { } func TestQueryResolver_Cards(t *testing.T) { + // Step 1: Create a Cardgroup + now := time.Now() + cardgroup := repository.Cardgroup{ + Name: "Test Cardgroup", + Created: now, + Updated: now, + } + db.Create(&cardgroup) + + // Step 2: Create a Card associated with the created Cardgroup card := repository.Card{ Front: "Front", Back: "Back", - ReviewDate: time.Now(), + ReviewDate: now, IntervalDays: 1, - CardGroupID: 1, - Created: time.Now(), - Updated: time.Now(), + CardGroupID: cardgroup.ID, // Ensure this matches the created Cardgroup ID + Created: now, + Updated: now, } db.Create(&card) + // Prepare GraphQL query jsonInput, _ := json.Marshal(map[string]interface{}{ "query": `{ cards { @@ -219,32 +301,45 @@ func TestQueryResolver_Cards(t *testing.T) { } }`, }) - expected := `{ + expected := fmt.Sprintf(`{ "data": { "cards": [{ - "id": ` + fmt.Sprintf("%d", card.ID) + `, + "id": %d, "front": "Front", - "back": "Back" + "back": "Back", + "interval_days": 1, }] } - }` - testGraphQLQuery(t, e, jsonInput, expected) + }`, card.ID) + + testGraphQLQuery(t, e, jsonInput, expected, "data.cards.created", "data.cards.updated", "data.cards.review_date") } func TestQueryResolver_Card(t *testing.T) { + // Step 1: Create a Cardgroup + now := time.Now() + cardgroup := repository.Cardgroup{ + Name: "Test Cardgroup", + Created: now, + Updated: now, + } + db.Create(&cardgroup) + + // Step 2: Create a Card associated with the created Cardgroup card := repository.Card{ Front: "Front", Back: "Back", - ReviewDate: time.Now(), + ReviewDate: now, IntervalDays: 1, - CardGroupID: 1, - Created: time.Now(), - Updated: time.Now(), + CardGroupID: cardgroup.ID, // Ensure this matches the created Cardgroup ID + Created: now, + Updated: now, } db.Create(&card) + // Prepare GraphQL query jsonInput, _ := json.Marshal(map[string]interface{}{ - "query": `query ($id: Int!) { + "query": `query ($id: ID!) { card(id: $id) { id front @@ -259,19 +354,18 @@ func TestQueryResolver_Card(t *testing.T) { "id": card.ID, }, }) - expected := `{ + expected := fmt.Sprintf(`{ "data": { "card": { - "id": ` + fmt.Sprintf("%d", card.ID) + `, + "id": %d, "front": "Front", "back": "Back" } } - }` - testGraphQLQuery(t, e, jsonInput, expected) -} + }`, card.ID) -// Add similar tests for the remaining resolvers + testGraphQLQuery(t, e, jsonInput, expected, "data.card.created", "data.card.updated", "data.card.review_date", "data.card.interval_days") +} func getDB() *gorm.DB { return db diff --git a/backend/pkg/flashcard/flashcard_system.go b/backend/pkg/flashcard/flashcard_system.go index 1be0867..33e1a12 100644 --- a/backend/pkg/flashcard/flashcard_system.go +++ b/backend/pkg/flashcard/flashcard_system.go @@ -42,7 +42,7 @@ func CreateCardReview(card *model.Card, db *gorm.DB) error { // MigrateDB performs the database migration for the Card struct func MigrateDB(db *gorm.DB) error { return db.AutoMigrate( - &model.CardGroup{}, + &model.Cardgroup{}, &model.Card{}, &model.User{}, &model.Role{}, diff --git a/backend/pkg/flashcard/flashcard_system_test.go b/backend/pkg/flashcard/flashcard_system_test.go index b86ad71..324874b 100644 --- a/backend/pkg/flashcard/flashcard_system_test.go +++ b/backend/pkg/flashcard/flashcard_system_test.go @@ -68,9 +68,9 @@ func setupTestDB(t *testing.T) (*gorm.DB, func()) { } } -func createTestCardGroup(t *testing.T, db *gorm.DB, name string) model.CardGroup { +func createTestCardGroup(t *testing.T, db *gorm.DB, name string) model.Cardgroup { t.Helper() - cardGroup := model.CardGroup{Name: name} + cardGroup := model.Cardgroup{Name: name} if err := db.Create(&cardGroup).Error; err != nil { t.Fatalf("could not create test card group: %v", err) } @@ -197,7 +197,7 @@ func TestFlashcardFunctions(t *testing.T) { assert.True(t, card.Updated.After(createdTime)) }) - t.Run("Test CardGroup Model", func(t *testing.T) { + t.Run("Test Cardgroup Model", func(t *testing.T) { assert.NotZero(t, cardGroup.ID) assert.Equal(t, "Test Group", cardGroup.Name) assert.NotZero(t, cardGroup.Created) @@ -225,14 +225,14 @@ func TestFlashcardFunctions(t *testing.T) { user := createTestUser(t, db, "user2", "Relationship User") role := createTestRole(t, db, "User") - // Test CardGroup - Card relationship - var fetchedCardGroup model.CardGroup + // Test Cardgroup - Card relationship + var fetchedCardGroup model.Cardgroup db.Preload("Cards").First(&fetchedCardGroup, cardGroup.ID) assert.Len(t, fetchedCardGroup.Cards, 2) assert.Equal(t, card1.ID, fetchedCardGroup.Cards[0].ID) assert.Equal(t, card2.ID, fetchedCardGroup.Cards[1].ID) - // Test User - CardGroup relationship + // Test User - Cardgroup relationship db.Model(&user).Association("CardGroups").Append(&cardGroup) var fetchedUser model.User db.Preload("CardGroups").First(&fetchedUser, "id = ?", user.ID) diff --git a/backend/pkg/model/model.go b/backend/pkg/model/model.go index 880efc0..09c24e1 100644 --- a/backend/pkg/model/model.go +++ b/backend/pkg/model/model.go @@ -5,36 +5,36 @@ import ( ) type User struct { - ID int64 `gorm:"primaryKey"` - Name string `gorm:"not null"` - Created time.Time `gorm:"autoCreateTime"` - Updated time.Time `gorm:"autoUpdateTime"` - CardGroups []CardGroup `gorm:"many2many:cardgroup_users"` + ID int64 `gorm:"column:id;primaryKey"` + Name string `gorm:"column:name;not null"` + Created time.Time `gorm:"column:created;autoCreateTime"` + Updated time.Time `gorm:"column:updated;autoUpdateTime"` + CardGroups []Cardgroup `gorm:"many2many:cardgroup_users"` Roles []Role `gorm:"many2many:user_roles"` } type Card struct { - ID int64 `gorm:"primaryKey"` - Front string `gorm:"not null"` - Back string `gorm:"not null"` - ReviewDate time.Time `gorm:"not null"` - IntervalDays int `gorm:"default:1;not null"` - Created time.Time `gorm:"autoCreateTime"` - Updated time.Time `gorm:"autoUpdateTime"` - CardGroupID int64 `gorm:"foreignKey:cardgroup_id"` + ID int64 `gorm:"column:id;primaryKey"` + Front string `gorm:"column:front;not null"` + Back string `gorm:"column:back;not null"` + ReviewDate time.Time `gorm:"column:review_date;not null"` + IntervalDays int `gorm:"column:interval_days;default:1;not null"` + Created time.Time `gorm:"column:created;autoCreateTime"` + Updated time.Time `gorm:"column:updated;autoUpdateTime"` + CardGroupID int64 `gorm:"column:cardgroup_id;foreignKey:cardgroup_id"` } -type CardGroup struct { - ID int64 `gorm:"primaryKey"` - Name string `gorm:"not null"` - Created time.Time `gorm:"autoCreateTime"` - Updated time.Time `gorm:"autoUpdateTime"` +type Cardgroup struct { + ID int64 `gorm:"column:id;primaryKey"` + Name string `gorm:"column:name;not null"` + Created time.Time `gorm:"column:created;autoCreateTime"` + Updated time.Time `gorm:"column:updated;autoUpdateTime"` Cards []Card `gorm:"foreignKey:cardgroup_id"` Users []User `gorm:"many2many:cardgroup_users"` } type Role struct { - ID int64 `gorm:"primaryKey"` - Name string `gorm:"not null"` + ID int64 `gorm:"column:id;primaryKey"` + Name string `gorm:"column:name;not null"` Users []User `gorm:"many2many:user_roles"` }