Enha: create tx; cardword test
This commit is contained in:
		| @@ -159,6 +159,21 @@ func HandleStartGame(w http.ResponseWriter, r *http.Request) { | |||||||
| 		abortWithError(w, err.Error()) | 		abortWithError(w, err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Initialize transaction | ||||||
|  | 	ctx, tx, err := repo.InitTx(r.Context()) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Error("failed to init transaction", "error", err) | ||||||
|  | 		abortWithError(w, err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	defer func() { | ||||||
|  | 		if r := recover(); r != nil { | ||||||
|  | 			tx.Rollback() | ||||||
|  | 			panic(r) | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  |  | ||||||
| 	fi.Room.IsRunning = true | 	fi.Room.IsRunning = true | ||||||
| 	fi.Room.IsOver = false | 	fi.Room.IsOver = false | ||||||
| 	fi.Room.TeamTurn = "blue" | 	fi.Room.TeamTurn = "blue" | ||||||
| @@ -174,10 +189,42 @@ func HandleStartGame(w http.ResponseWriter, r *http.Request) { | |||||||
| 		Action:     models.ActionTypeGameStarted, | 		Action:     models.ActionTypeGameStarted, | ||||||
| 	} | 	} | ||||||
| 	fi.Room.ActionHistory = append(fi.Room.ActionHistory, action) | 	fi.Room.ActionHistory = append(fi.Room.ActionHistory, action) | ||||||
| 	if err := saveFullInfo(r.Context(), fi); err != nil { |  | ||||||
|  | 	// Use the new context with transaction | ||||||
|  | 	if err := saveFullInfo(ctx, fi); err != nil { | ||||||
|  | 		tx.Rollback() | ||||||
| 		abortWithError(w, err.Error()) | 		abortWithError(w, err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Save action history | ||||||
|  | 	action.RoomID = fi.Room.ID | ||||||
|  | 	action.CreatedAtUnix = time.Now().Unix() | ||||||
|  | 	if err := repo.CreateAction(ctx, fi.Room.ID, &action); err != nil { | ||||||
|  | 		tx.Rollback() | ||||||
|  | 		log.Error("failed to save action", "error", err) | ||||||
|  | 		abortWithError(w, err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Save word cards | ||||||
|  | 	for _, card := range fi.Room.Cards { | ||||||
|  | 		card.RoomID = fi.Room.ID // Ensure RoomID is set for each card | ||||||
|  | 		if err := repo.WordCardsCreate(ctx, &card); err != nil { | ||||||
|  | 			tx.Rollback() | ||||||
|  | 			log.Error("failed to save word card", "error", err) | ||||||
|  | 			abortWithError(w, err.Error()) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Commit the transaction | ||||||
|  | 	if err := tx.Commit(); err != nil { | ||||||
|  | 		log.Error("failed to commit transaction", "error", err) | ||||||
|  | 		abortWithError(w, err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// reveal all cards | 	// reveal all cards | ||||||
| 	if fi.State.Role == "mime" { | 	if fi.State.Role == "mime" { | ||||||
| 		fi.Room.MimeView() | 		fi.Room.MimeView() | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ type AllRepos interface { | |||||||
| 	PlayersRepo | 	PlayersRepo | ||||||
| 	SessionsRepo | 	SessionsRepo | ||||||
| 	WordCardsRepo | 	WordCardsRepo | ||||||
|  | 	InitTx(ctx context.Context) (context.Context, *sqlx.Tx, error) | ||||||
| } | } | ||||||
|  |  | ||||||
| type RepoProvider struct { | type RepoProvider struct { | ||||||
| @@ -95,3 +96,11 @@ func getDB(ctx context.Context, db *sqlx.DB) sqlx.ExtContext { | |||||||
| 	} | 	} | ||||||
| 	return db | 	return db | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (p *RepoProvider) InitTx(ctx context.Context) (context.Context, *sqlx.Tx, error) { | ||||||
|  | 	tx, err := p.DB.BeginTxx(ctx, nil) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, nil, err | ||||||
|  | 	} | ||||||
|  | 	return context.WithValue(ctx, "tx", tx), tx, nil | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										496
									
								
								repos/word_cards_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										496
									
								
								repos/word_cards_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,496 @@ | |||||||
|  | package repos | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"gralias/models" | ||||||
|  | 	"os" | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/jmoiron/sqlx" | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | 	_ "github.com/mattn/go-sqlite3" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestWordCardsRepo_Create(t *testing.T) { | ||||||
|  | 	// Setup temporary file-based SQLite database for this test | ||||||
|  | 	tempFile, err := os.CreateTemp("", "test_db_*.db") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	tempFile.Close() | ||||||
|  | 	defer os.Remove(tempFile.Name()) | ||||||
|  |  | ||||||
|  | 	db, err := sqlx.Connect("sqlite3", tempFile.Name()) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	defer db.Close() | ||||||
|  |  | ||||||
|  | 	// Enable foreign key constraints | ||||||
|  | 	_, err = db.Exec("PRAGMA foreign_keys = ON;") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// Apply schema | ||||||
|  | 	schema := ` | ||||||
|  | 	CREATE TABLE IF NOT EXISTS rooms ( | ||||||
|  | 		id TEXT PRIMARY KEY, | ||||||
|  | 		created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||||
|  | 		creator_name TEXT NOT NULL | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	CREATE TABLE IF NOT EXISTS word_cards ( | ||||||
|  | 		id INTEGER PRIMARY KEY AUTOINCREMENT, | ||||||
|  | 		room_id TEXT NOT NULL, | ||||||
|  | 		word TEXT NOT NULL, | ||||||
|  | 		color TEXT NOT NULL DEFAULT '', | ||||||
|  | 		revealed BOOLEAN NOT NULL DEFAULT FALSE, | ||||||
|  | 		mime_view BOOLEAN NOT NULL DEFAULT FALSE, | ||||||
|  | 		FOREIGN KEY (room_id) REFERENCES rooms(id) ON DELETE CASCADE | ||||||
|  | 	); | ||||||
|  | 	` | ||||||
|  | 	_, err = db.Exec(schema) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	ctx := context.Background() | ||||||
|  |  | ||||||
|  | 	roomID := "test_room_1" | ||||||
|  | 	// Insert a room first, as word_cards has a foreign key to rooms | ||||||
|  | 	_, err = db.Exec(`INSERT INTO rooms (id, created_at, creator_name) VALUES (?, ?, ?)`, roomID, time.Now(), "test_creator") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// Test single card creation | ||||||
|  | 	card1 := &models.WordCard{ | ||||||
|  | 		RoomID:   roomID, | ||||||
|  | 		Word:     "apple", | ||||||
|  | 		Color:    models.WordColorRed, | ||||||
|  | 		Revealed: false, | ||||||
|  | 		Mime:     false, | ||||||
|  | 	} | ||||||
|  | 	_, err = db.Exec(`INSERT INTO word_cards (room_id, word, color, revealed, mime_view) VALUES (?, ?, ?, ?, ?)`, card1.RoomID, card1.Word, card1.Color, card1.Revealed, card1.Mime) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	var count int | ||||||
|  | 	err = db.Get(&count, "SELECT COUNT(*) FROM word_cards WHERE room_id = ?", roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	assert.Equal(t, 1, count) | ||||||
|  |  | ||||||
|  | 	// Test batch card creation with transaction commit | ||||||
|  | 	tx, err := db.BeginTxx(ctx, nil) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	card2 := &models.WordCard{ | ||||||
|  | 		RoomID:   roomID, | ||||||
|  | 		Word:     "banana", | ||||||
|  | 		Color:    models.WordColorBlue, | ||||||
|  | 		Revealed: false, | ||||||
|  | 		Mime:     false, | ||||||
|  | 	} | ||||||
|  | 	card3 := &models.WordCard{ | ||||||
|  | 		RoomID:   roomID, | ||||||
|  | 		Word:     "cherry", | ||||||
|  | 		Color:    models.WordColorBlack, | ||||||
|  | 		Revealed: false, | ||||||
|  | 		Mime:     false, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	_, err = tx.Exec(`INSERT INTO word_cards (room_id, word, color, revealed, mime_view) VALUES (?, ?, ?, ?, ?)`, card2.RoomID, card2.Word, card2.Color, card2.Revealed, card2.Mime) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	_, err = tx.Exec(`INSERT INTO word_cards (room_id, word, color, revealed, mime_view) VALUES (?, ?, ?, ?, ?)`, card3.RoomID, card3.Word, card3.Color, card3.Revealed, card3.Mime) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// Before commit, count should not reflect changes if using a transaction context | ||||||
|  | 	err = db.Get(&count, "SELECT COUNT(*) FROM word_cards WHERE room_id = ?", roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	assert.Equal(t, 1, count) // Should still be 1 if not committed | ||||||
|  |  | ||||||
|  | 	err = tx.Commit() | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// After commit, count should reflect changes | ||||||
|  | 	err = db.Get(&count, "SELECT COUNT(*) FROM word_cards WHERE room_id = ?", roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	assert.Equal(t, 3, count) | ||||||
|  |  | ||||||
|  | 	// Test transaction rollback | ||||||
|  | 	tx2, err := db.BeginTxx(ctx, nil) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	card4 := &models.WordCard{ | ||||||
|  | 		RoomID:   roomID, | ||||||
|  | 		Word:     "date", | ||||||
|  | 		Color:    models.WordColorWhite, | ||||||
|  | 		Revealed: false, | ||||||
|  | 		Mime:     false, | ||||||
|  | 	} | ||||||
|  | 	_, err = tx2.Exec(`INSERT INTO word_cards (room_id, word, color, revealed, mime_view) VALUES (?, ?, ?, ?, ?)`, card4.RoomID, card4.Word, card4.Color, card4.Revealed, card4.Mime) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	err = tx2.Rollback() | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// After rollback, count should not reflect changes | ||||||
|  | 	err = db.Get(&count, "SELECT COUNT(*) FROM word_cards WHERE room_id = ?", roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	assert.Equal(t, 3, count) | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | func TestWordCardsRepo_GetByWordAndRoomID(t *testing.T) { | ||||||
|  | 	// Setup temporary file-based SQLite database for this test | ||||||
|  | 	tempFile, err := os.CreateTemp("", "test_db_*.db") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	tempFile.Close() | ||||||
|  | 	defer os.Remove(tempFile.Name()) | ||||||
|  |  | ||||||
|  | 	db, err := sqlx.Connect("sqlite3", tempFile.Name()) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	defer db.Close() | ||||||
|  |  | ||||||
|  | 	// Enable foreign key constraints | ||||||
|  | 	_, err = db.Exec("PRAGMA foreign_keys = ON;") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// Apply schema | ||||||
|  | 	schema := ` | ||||||
|  | 	CREATE TABLE IF NOT EXISTS rooms ( | ||||||
|  | 		id TEXT PRIMARY KEY, | ||||||
|  | 		created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||||
|  | 		creator_name TEXT NOT NULL | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	CREATE TABLE IF NOT EXISTS word_cards ( | ||||||
|  | 		id INTEGER PRIMARY KEY AUTOINCREMENT, | ||||||
|  | 		room_id TEXT NOT NULL, | ||||||
|  | 		word TEXT NOT NULL, | ||||||
|  | 		color TEXT NOT NULL DEFAULT '', | ||||||
|  | 		revealed BOOLEAN NOT NULL DEFAULT FALSE, | ||||||
|  | 		mime_view BOOLEAN NOT NULL DEFAULT FALSE, | ||||||
|  | 		FOREIGN KEY (room_id) REFERENCES rooms(id) ON DELETE CASCADE | ||||||
|  | 	); | ||||||
|  | 	` | ||||||
|  | 	_, err = db.Exec(schema) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	repo := &RepoProvider{DB: db} | ||||||
|  | 	ctx := context.Background() | ||||||
|  |  | ||||||
|  | 	roomID := "test_room_3" | ||||||
|  | 	_, err = db.Exec(`INSERT INTO rooms (id, created_at, creator_name) VALUES (?, ?, ?)`, roomID, time.Now(), "test_creator") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	card := &models.WordCard{ | ||||||
|  | 		RoomID:   roomID, | ||||||
|  | 		Word:     "gamma", | ||||||
|  | 		Color:    models.WordColorRed, | ||||||
|  | 		Revealed: false, | ||||||
|  | 		Mime:     false, | ||||||
|  | 	} | ||||||
|  | 	err = repo.WordCardsCreate(ctx, card) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	retrievedCard, err := repo.WordCardGetByWordAndRoomID(ctx, "gamma", roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	assert.NotNil(t, retrievedCard) | ||||||
|  | 	assert.Equal(t, "gamma", retrievedCard.Word) | ||||||
|  | 	assert.Equal(t, roomID, retrievedCard.RoomID) | ||||||
|  |  | ||||||
|  | 	// Test non-existent card | ||||||
|  | 	_, err = repo.WordCardGetByWordAndRoomID(ctx, "non_existent", roomID) | ||||||
|  | 	assert.Error(t, err) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestWordCardsRepo_Reveal(t *testing.T) { | ||||||
|  | 	// Setup temporary file-based SQLite database for this test | ||||||
|  | 	tempFile, err := os.CreateTemp("", "test_db_*.db") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	tempFile.Close() | ||||||
|  | 	defer os.Remove(tempFile.Name()) | ||||||
|  |  | ||||||
|  | 	db, err := sqlx.Connect("sqlite3", tempFile.Name()) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	defer db.Close() | ||||||
|  |  | ||||||
|  | 	// Enable foreign key constraints | ||||||
|  | 	_, err = db.Exec("PRAGMA foreign_keys = ON;") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// Apply schema | ||||||
|  | 	schema := ` | ||||||
|  | 	CREATE TABLE IF NOT EXISTS rooms ( | ||||||
|  | 		id TEXT PRIMARY KEY, | ||||||
|  | 		created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||||
|  | 		creator_name TEXT NOT NULL | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	CREATE TABLE IF NOT EXISTS word_cards ( | ||||||
|  | 		id INTEGER PRIMARY KEY AUTOINCREMENT, | ||||||
|  | 		room_id TEXT NOT NULL, | ||||||
|  | 		word TEXT NOT NULL, | ||||||
|  | 		color TEXT NOT NULL DEFAULT '', | ||||||
|  | 		revealed BOOLEAN NOT NULL DEFAULT FALSE, | ||||||
|  | 		mime_view BOOLEAN NOT NULL DEFAULT FALSE, | ||||||
|  | 		FOREIGN KEY (room_id) REFERENCES rooms(id) ON DELETE CASCADE | ||||||
|  | 	); | ||||||
|  | 	` | ||||||
|  | 	_, err = db.Exec(schema) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	repo := &RepoProvider{DB: db} | ||||||
|  | 	ctx := context.Background() | ||||||
|  |  | ||||||
|  | 	roomID := "test_room_4" | ||||||
|  | 	_, err = db.Exec(`INSERT INTO rooms (id, created_at, creator_name) VALUES (?, ?, ?)`, roomID, time.Now(), "test_creator") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	card := &models.WordCard{ | ||||||
|  | 		RoomID:   roomID, | ||||||
|  | 		Word:     "delta", | ||||||
|  | 		Color:    models.WordColorRed, | ||||||
|  | 		Revealed: false, | ||||||
|  | 		Mime:     false, | ||||||
|  | 	} | ||||||
|  | 	err = repo.WordCardsCreate(ctx, card) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// Verify initial state | ||||||
|  | 	var revealed bool | ||||||
|  | 	err = db.Get(&revealed, "SELECT revealed FROM word_cards WHERE word = ? AND room_id = ?", "delta", roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	assert.False(t, revealed) | ||||||
|  |  | ||||||
|  | 	// Reveal the card | ||||||
|  | 	err = repo.WordCardReveal(ctx, "delta", roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// Verify revealed state | ||||||
|  | 	err = db.Get(&revealed, "SELECT revealed FROM word_cards WHERE word = ? AND room_id = ?", "delta", roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	assert.True(t, revealed) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestWordCardsRepo_RevealAll(t *testing.T) { | ||||||
|  | 	// Setup temporary file-based SQLite database for this test | ||||||
|  | 	tempFile, err := os.CreateTemp("", "test_db_*.db") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	tempFile.Close() | ||||||
|  | 	defer os.Remove(tempFile.Name()) | ||||||
|  |  | ||||||
|  | 	db, err := sqlx.Connect("sqlite3", tempFile.Name()) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	defer db.Close() | ||||||
|  |  | ||||||
|  | 	// Enable foreign key constraints | ||||||
|  | 	_, err = db.Exec("PRAGMA foreign_keys = ON;") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// Apply schema | ||||||
|  | 	schema := ` | ||||||
|  | 	CREATE TABLE IF NOT EXISTS rooms ( | ||||||
|  | 		id TEXT PRIMARY KEY, | ||||||
|  | 		created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||||
|  | 		creator_name TEXT NOT NULL | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	CREATE TABLE IF NOT EXISTS word_cards ( | ||||||
|  | 		id INTEGER PRIMARY KEY AUTOINCREMENT, | ||||||
|  | 		room_id TEXT NOT NULL, | ||||||
|  | 		word TEXT NOT NULL, | ||||||
|  | 		color TEXT NOT NULL DEFAULT '', | ||||||
|  | 		revealed BOOLEAN NOT NULL DEFAULT FALSE, | ||||||
|  | 		mime_view BOOLEAN NOT NULL DEFAULT FALSE, | ||||||
|  | 		FOREIGN KEY (room_id) REFERENCES rooms(id) ON DELETE CASCADE | ||||||
|  | 	); | ||||||
|  | 	` | ||||||
|  | 	_, err = db.Exec(schema) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	repo := &RepoProvider{DB: db} | ||||||
|  | 	ctx := context.Background() | ||||||
|  |  | ||||||
|  | 	roomID := "test_room_5" | ||||||
|  | 	_, err = db.Exec(`INSERT INTO rooms (id, created_at, creator_name) VALUES (?, ?, ?)`, roomID, time.Now(), "test_creator") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	cardsToInsert := []*models.WordCard{ | ||||||
|  | 		{ | ||||||
|  | 			RoomID:   roomID, | ||||||
|  | 			Word:     "echo", | ||||||
|  | 			Color:    models.WordColorRed, | ||||||
|  | 			Revealed: false, | ||||||
|  | 			Mime:     false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			RoomID:   roomID, | ||||||
|  | 			Color:    models.WordColorBlue, | ||||||
|  | 			Revealed: false, | ||||||
|  | 			Mime:     false, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, card := range cardsToInsert { | ||||||
|  | 		err = repo.WordCardsCreate(ctx, card) | ||||||
|  | 		assert.NoError(t, err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Verify initial state | ||||||
|  | 	var count int | ||||||
|  | 	err = db.Get(&count, "SELECT COUNT(*) FROM word_cards WHERE room_id = ? AND revealed = FALSE", roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	assert.Equal(t, 2, count) | ||||||
|  |  | ||||||
|  | 	// Reveal all cards | ||||||
|  | 	err = repo.WordCardsRevealAll(ctx, roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// Verify all cards are revealed | ||||||
|  | 	err = db.Get(&count, "SELECT COUNT(*) FROM word_cards WHERE room_id = ? AND revealed = FALSE", roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	assert.Equal(t, 0, count) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestWordCardsRepo_DeleteByRoomID(t *testing.T) { | ||||||
|  | 	// Setup temporary file-based SQLite database for this test | ||||||
|  | 	tempFile, err := os.CreateTemp("", "test_db_*.db") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	tempFile.Close() | ||||||
|  | 	defer os.Remove(tempFile.Name()) | ||||||
|  |  | ||||||
|  | 	db, err := sqlx.Connect("sqlite3", tempFile.Name()) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	defer db.Close() | ||||||
|  |  | ||||||
|  | 	// Enable foreign key constraints | ||||||
|  | 	_, err = db.Exec("PRAGMA foreign_keys = ON;") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// Apply schema | ||||||
|  | 	schema := ` | ||||||
|  | 	CREATE TABLE IF NOT EXISTS rooms ( | ||||||
|  | 		id TEXT PRIMARY KEY, | ||||||
|  | 		created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||||
|  | 		creator_name TEXT NOT NULL | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	CREATE TABLE IF NOT EXISTS word_cards ( | ||||||
|  | 		id INTEGER PRIMARY KEY AUTOINCREMENT, | ||||||
|  | 		room_id TEXT NOT NULL, | ||||||
|  | 		word TEXT NOT NULL, | ||||||
|  | 		color TEXT NOT NULL DEFAULT '', | ||||||
|  | 		revealed BOOLEAN NOT NULL DEFAULT FALSE, | ||||||
|  | 		mime_view BOOLEAN NOT NULL DEFAULT FALSE, | ||||||
|  | 		FOREIGN KEY (room_id) REFERENCES rooms(id) ON DELETE CASCADE | ||||||
|  | 	); | ||||||
|  | 	` | ||||||
|  | 	_, err = db.Exec(schema) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	repo := &RepoProvider{DB: db} | ||||||
|  | 	ctx := context.Background() | ||||||
|  |  | ||||||
|  | 	roomID := "test_room_6" | ||||||
|  | 	_, err = db.Exec(`INSERT INTO rooms (id, created_at, creator_name) VALUES (?, ?, ?)`, roomID, time.Now(), "test_creator") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	cardsToInsert := []*models.WordCard{ | ||||||
|  | 		{ | ||||||
|  | 			RoomID:   roomID, | ||||||
|  | 			Word:     "golf", | ||||||
|  | 			Color:    models.WordColorRed, | ||||||
|  | 			Revealed: false, | ||||||
|  | 			Mime:     false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			RoomID:   roomID, | ||||||
|  | 			Word:     "hotel", | ||||||
|  | 			Color:    models.WordColorBlue, | ||||||
|  | 			Revealed: false, | ||||||
|  | 			Mime:     false, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, card := range cardsToInsert { | ||||||
|  | 		err = repo.WordCardsCreate(ctx, card) | ||||||
|  | 		assert.NoError(t, err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Verify initial state | ||||||
|  | 	var count int | ||||||
|  | 	err = db.Get(&count, "SELECT COUNT(*) FROM word_cards WHERE room_id = ?", roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	assert.Equal(t, 2, count) | ||||||
|  |  | ||||||
|  | 	// Delete cards by room ID | ||||||
|  | 	err = repo.WordCardsDeleteByRoomID(ctx, roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// Verify cards are deleted | ||||||
|  | 	err = db.Get(&count, "SELECT COUNT(*) FROM word_cards WHERE room_id = ?", roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	assert.Equal(t, 0, count) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestWordCardsRepo_CascadeDeleteRoom(t *testing.T) { | ||||||
|  | 	// Setup temporary file-based SQLite database for this test | ||||||
|  | 	tempFile, err := os.CreateTemp("", "test_db_*.db") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	tempFile.Close() | ||||||
|  | 	defer os.Remove(tempFile.Name()) | ||||||
|  |  | ||||||
|  | 	db, err := sqlx.Connect("sqlite3", tempFile.Name()) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	defer db.Close() | ||||||
|  |  | ||||||
|  | 	// Enable foreign key constraints | ||||||
|  | 	_, err = db.Exec("PRAGMA foreign_keys = ON;") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	// Apply schema | ||||||
|  | 	schema := ` | ||||||
|  | 	CREATE TABLE IF NOT EXISTS rooms ( | ||||||
|  | 		id TEXT PRIMARY KEY, | ||||||
|  | 		created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||||
|  | 		creator_name TEXT NOT NULL | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	CREATE TABLE IF NOT EXISTS word_cards ( | ||||||
|  | 		id INTEGER PRIMARY KEY AUTOINCREMENT, | ||||||
|  | 		room_id TEXT NOT NULL, | ||||||
|  | 		word TEXT NOT NULL, | ||||||
|  | 		color TEXT NOT NULL DEFAULT '', | ||||||
|  | 		revealed BOOLEAN NOT NULL DEFAULT FALSE, | ||||||
|  | 		mime_view BOOLEAN NOT NULL DEFAULT FALSE, | ||||||
|  | 		FOREIGN KEY (room_id) REFERENCES rooms(id) ON DELETE CASCADE | ||||||
|  | 	); | ||||||
|  | 	` | ||||||
|  | 	_, err = db.Exec(schema) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	repo := &RepoProvider{DB: db} | ||||||
|  | 	ctx := context.Background() | ||||||
|  |  | ||||||
|  | 	roomID := "test_room_7" | ||||||
|  | 	_, err = db.Exec(`INSERT INTO rooms (id, created_at, creator_name) VALUES (?, ?, ?)`, roomID, time.Now(), "test_creator") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	card := &models.WordCard{ | ||||||
|  | 		RoomID:   roomID, | ||||||
|  | 		Word:     "india", | ||||||
|  | 		Color:    models.WordColorRed, | ||||||
|  | 		Revealed: false, | ||||||
|  | 		Mime:     false, | ||||||
|  | 	} | ||||||
|  | 	err = repo.WordCardsCreate(ctx, card) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	var count int | ||||||
|  | 	err = db.Get(&count, "SELECT COUNT(*) FROM word_cards WHERE room_id = ?", roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	assert.Equal(t, 1, count) | ||||||
|  |  | ||||||
|  | 	_, err = db.Exec(`DELETE FROM rooms WHERE id = ?`, roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  |  | ||||||
|  | 	err = db.Get(&count, "SELECT COUNT(*) FROM word_cards WHERE room_id = ?", roomID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	assert.Equal(t, 0, count) | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
		Reference in New Issue
	
	Block a user
	 Grail Finder
					Grail Finder