Fix: unittests
This commit is contained in:
@ -75,13 +75,13 @@ func createRoom(ctx context.Context, req *models.RoomReq) (*models.Room, error)
|
|||||||
// repo.CreateRoom()
|
// repo.CreateRoom()
|
||||||
// }
|
// }
|
||||||
|
|
||||||
func saveFullInfo(fi *models.FullInfo) error {
|
func saveFullInfo(ctx context.Context, fi *models.FullInfo) error {
|
||||||
// INFO: no transactions; so case is possible where first object is updated but the second is not
|
// INFO: no transactions; so case is possible where first object is updated but the second is not
|
||||||
if err := repo.PlayerUpdate(fi.State); err != nil {
|
if err := repo.PlayerUpdate(ctx, fi.State); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Debug("saved user state", "state", fi.State)
|
log.Debug("saved user state", "state", fi.State)
|
||||||
if err := repo.RoomUpdate(context.Background(), fi.Room); err != nil {
|
if err := repo.RoomUpdate(ctx, fi.Room); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -155,7 +155,7 @@ func getPlayerByCtx(ctx context.Context) (*models.Player, error) {
|
|||||||
log.Debug("no username in ctx")
|
log.Debug("no username in ctx")
|
||||||
return &models.Player{}, errors.New("no username in ctx")
|
return &models.Player{}, errors.New("no username in ctx")
|
||||||
}
|
}
|
||||||
return repo.PlayerGetByName(username)
|
return repo.PlayerGetByName(ctx, username)
|
||||||
}
|
}
|
||||||
|
|
||||||
// // DEPRECATED
|
// // DEPRECATED
|
||||||
@ -219,7 +219,7 @@ func joinTeam(ctx context.Context, role, team string) (*models.FullInfo, error)
|
|||||||
err := errors.New("uknown role:" + role)
|
err := errors.New("uknown role:" + role)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := saveFullInfo(fi); err != nil {
|
if err := saveFullInfo(ctx, fi); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return fi, nil
|
return fi, nil
|
||||||
@ -247,7 +247,7 @@ func joinTeam(ctx context.Context, role, team string) (*models.FullInfo, error)
|
|||||||
|
|
||||||
// get bots
|
// get bots
|
||||||
func listBots() []models.Player {
|
func listBots() []models.Player {
|
||||||
bots, err := repo.PlayerList(true)
|
bots, err := repo.PlayerList(context.Background(), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("failed to fetch bots from db", "error", err)
|
log.Error("failed to fetch bots from db", "error", err)
|
||||||
}
|
}
|
||||||
|
@ -1,107 +0,0 @@
|
|||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"gralias/models"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSaveState(t *testing.T) {
|
|
||||||
// Create test state
|
|
||||||
state := &models.UserState{
|
|
||||||
Username: "testuser",
|
|
||||||
RoomID: "testroom",
|
|
||||||
Team: models.UserTeamBlue,
|
|
||||||
Role: models.UserRoleMime,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save state
|
|
||||||
err := saveState(state.Username, state)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("saveState failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load state
|
|
||||||
loadedState, err := loadState(state.Username)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("loadState failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify loaded state matches original
|
|
||||||
if loadedState.Username != state.Username {
|
|
||||||
t.Errorf("Username mismatch: got %s, want %s", loadedState.Username, state.Username)
|
|
||||||
}
|
|
||||||
if loadedState.RoomID != state.RoomID {
|
|
||||||
t.Errorf("RoomID mismatch: got %s, want %s", loadedState.RoomID, state.RoomID)
|
|
||||||
}
|
|
||||||
if loadedState.Team != state.Team {
|
|
||||||
t.Errorf("Team mismatch: got %s, want %s", loadedState.Team, state.Team)
|
|
||||||
}
|
|
||||||
if loadedState.Role != state.Role {
|
|
||||||
t.Errorf("Role mismatch: got %s, want %s", loadedState.Role, state.Role)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test JSON serialization/deserialization
|
|
||||||
data, err := json.Marshal(state)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("marshal failed: %v", err)
|
|
||||||
}
|
|
||||||
testMap := make(map[string][]byte)
|
|
||||||
testMap["testkey"] = data
|
|
||||||
|
|
||||||
// Create a temporary file
|
|
||||||
tmpFile, err := os.CreateTemp("", "test_store_*.json")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to create temp file: %v", err)
|
|
||||||
}
|
|
||||||
tmpFileName := tmpFile.Name()
|
|
||||||
// defer os.Remove(tmpFileName)
|
|
||||||
|
|
||||||
// Write testMap to the temp file
|
|
||||||
fileData, err := json.Marshal(testMap)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to marshal testMap: %v", err)
|
|
||||||
}
|
|
||||||
if err := os.WriteFile(tmpFileName, fileData, 0644); err != nil {
|
|
||||||
t.Fatalf("failed to write to temp file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the temp file
|
|
||||||
readData, err := os.ReadFile(tmpFileName)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to read temp file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal the data
|
|
||||||
var testMapRead map[string][]byte
|
|
||||||
if err := json.Unmarshal(readData, &testMapRead); err != nil {
|
|
||||||
t.Fatalf("failed to unmarshal testMap: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the state bytes from the map
|
|
||||||
stateBytes, ok := testMapRead["testkey"]
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("key 'testkey' not found in testMapRead")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal the state bytes
|
|
||||||
stateRead := &models.UserState{}
|
|
||||||
if err := json.Unmarshal(stateBytes, stateRead); err != nil {
|
|
||||||
t.Fatalf("failed to unmarshal state: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare the state
|
|
||||||
if stateRead.Username != state.Username {
|
|
||||||
t.Errorf("Username mismatch from file: got %s, want %s", stateRead.Username, state.Username)
|
|
||||||
}
|
|
||||||
if stateRead.RoomID != state.RoomID {
|
|
||||||
t.Errorf("RoomID mismatch from file: got %s, want %s", stateRead.RoomID, state.RoomID)
|
|
||||||
}
|
|
||||||
if stateRead.Team != state.Team {
|
|
||||||
t.Errorf("Team mismatch from file: got %s, want %s", stateRead.Team, state.Team)
|
|
||||||
}
|
|
||||||
if stateRead.Role != state.Role {
|
|
||||||
t.Errorf("Role mismatch from file: got %s, want %s", stateRead.Role, state.Role)
|
|
||||||
}
|
|
||||||
}
|
|
@ -37,7 +37,7 @@ func HandleNameCheck(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
cleanName := utils.RemoveSpacesFromStr(username)
|
cleanName := utils.RemoveSpacesFromStr(username)
|
||||||
// allNames := getAllNames()
|
// allNames := getAllNames()
|
||||||
allNames, err := repo.PlayerListNames()
|
allNames, err := repo.PlayerListNames(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
@ -86,7 +86,7 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.SetCookie(w, cookie)
|
http.SetCookie(w, cookie)
|
||||||
// check if that user was already in db
|
// check if that user was already in db
|
||||||
// userstate, err := loadState(cleanName)
|
// userstate, err := loadState(cleanName)
|
||||||
userstate, err := repo.PlayerGetByName(cleanName)
|
userstate, err := repo.PlayerGetByName(r.Context(), cleanName)
|
||||||
if err != nil || userstate == nil {
|
if err != nil || userstate == nil {
|
||||||
userstate = models.InitPlayer(cleanName)
|
userstate = models.InitPlayer(cleanName)
|
||||||
}
|
}
|
||||||
@ -106,10 +106,10 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) {
|
|||||||
fi.Room = room
|
fi.Room = room
|
||||||
fi.List = nil
|
fi.List = nil
|
||||||
fi.State.RoomID = room.ID
|
fi.State.RoomID = room.ID
|
||||||
repo.PlayerSetRoomID(fi.State.Username, room.ID)
|
repo.PlayerSetRoomID(r.Context(), fi.State.Username, room.ID)
|
||||||
// repo.RoomUpdate()
|
// repo.RoomUpdate()
|
||||||
// save full info instead
|
// save full info instead
|
||||||
// if err := saveFullInfo(fi); err != nil {
|
// if err := saveFullInfo(r.Context(), fi); err != nil {
|
||||||
// abortWithError(w, err.Error())
|
// abortWithError(w, err.Error())
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
@ -123,8 +123,8 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
// save state to cache
|
// save state to cache
|
||||||
// if err := saveState(cleanName, userstate); err != nil {
|
// if err := saveState(cleanName, userstate); err != nil {
|
||||||
if err := repo.PlayerUpdate(userstate); err != nil {
|
if err := repo.PlayerUpdate(r.Context(), userstate); err != nil {
|
||||||
// if err := saveFullInfo(fi); err != nil {
|
// if err := saveFullInfo(r.Context(), fi); err != nil {
|
||||||
log.Error("failed to save state", "error", err)
|
log.Error("failed to save state", "error", err)
|
||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
|
@ -157,7 +157,7 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) {
|
|||||||
fi.Room.ClearMarks()
|
fi.Room.ClearMarks()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := saveFullInfo(fi); err != nil {
|
if err := saveFullInfo(r.Context(), fi); err != nil {
|
||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -221,7 +221,7 @@ func HandleMarkCard(w http.ResponseWriter, r *http.Request) {
|
|||||||
fi.Room.Cards[i].Mark = newMarks
|
fi.Room.Cards[i].Mark = newMarks
|
||||||
cardword = fi.Room.Cards[i]
|
cardword = fi.Room.Cards[i]
|
||||||
}
|
}
|
||||||
if err := saveFullInfo(fi); err != nil {
|
if err := saveFullInfo(r.Context(), fi); err != nil {
|
||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -46,11 +46,11 @@ func HandleCreateRoom(w http.ResponseWriter, r *http.Request) {
|
|||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := repo.PlayerSetRoomID(fi.State.Username, room.ID); err != nil {
|
if err := repo.PlayerSetRoomID(r.Context(), fi.State.Username, room.ID); err != nil {
|
||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// if err := saveFullInfo(fi); err != nil {
|
// if err := saveFullInfo(r.Context(), fi); err != nil {
|
||||||
// msg := "failed to set current room to session"
|
// msg := "failed to set current room to session"
|
||||||
// log.Error(msg, "error", err)
|
// log.Error(msg, "error", err)
|
||||||
// abortWithError(w, msg)
|
// abortWithError(w, msg)
|
||||||
@ -131,7 +131,7 @@ func HandleEndTurn(w http.ResponseWriter, r *http.Request) {
|
|||||||
fi.Room.ChangeTurn()
|
fi.Room.ChangeTurn()
|
||||||
fi.Room.MimeDone = false
|
fi.Room.MimeDone = false
|
||||||
StopTurnTimer(fi.Room.ID)
|
StopTurnTimer(fi.Room.ID)
|
||||||
if err := saveFullInfo(fi); err != nil {
|
if err := saveFullInfo(r.Context(), fi); err != nil {
|
||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -174,7 +174,7 @@ 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(fi); err != nil {
|
if err := saveFullInfo(r.Context(), fi); err != nil {
|
||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -226,7 +226,7 @@ func HandleJoinRoom(w http.ResponseWriter, r *http.Request) {
|
|||||||
fi.State.RoomID = room.ID
|
fi.State.RoomID = room.ID
|
||||||
fi.Room = room
|
fi.Room = room
|
||||||
fi.List = nil
|
fi.List = nil
|
||||||
if err := saveFullInfo(fi); err != nil {
|
if err := saveFullInfo(r.Context(), fi); err != nil {
|
||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -297,7 +297,7 @@ func HandleGiveClue(w http.ResponseWriter, r *http.Request) {
|
|||||||
log.Debug("given clue", "clue", clue, "limit", fi.Room.ThisTurnLimit)
|
log.Debug("given clue", "clue", clue, "limit", fi.Room.ThisTurnLimit)
|
||||||
notify(models.NotifyBacklogPrefix+fi.Room.ID, clue+num)
|
notify(models.NotifyBacklogPrefix+fi.Room.ID, clue+num)
|
||||||
notifyBotIfNeeded(fi.Room)
|
notifyBotIfNeeded(fi.Room)
|
||||||
if err := saveFullInfo(fi); err != nil {
|
if err := saveFullInfo(r.Context(), fi); err != nil {
|
||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -103,11 +103,14 @@ func HandleExit(w http.ResponseWriter, r *http.Request) {
|
|||||||
notify(models.NotifyRoomListUpdate, "")
|
notify(models.NotifyRoomListUpdate, "")
|
||||||
}
|
}
|
||||||
// scary to update the whole room
|
// scary to update the whole room
|
||||||
if err := repo.RoomUpdate(r.Context(), exitedRoom); err != nil {
|
fiToSave := &models.FullInfo{
|
||||||
|
Room: exitedRoom,
|
||||||
|
}
|
||||||
|
if err := saveFullInfo(r.Context(), fiToSave); err != nil {
|
||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := repo.PlayerExitRoom(fi.State.Username); err != nil {
|
if err := repo.PlayerExitRoom(r.Context(), fi.State.Username); err != nil {
|
||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@ type (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// Context keys
|
||||||
|
TxContextKey = "tx"
|
||||||
// UserTeam
|
// UserTeam
|
||||||
UserTeamBlue = "blue"
|
UserTeamBlue = "blue"
|
||||||
UserTeamRed = "red"
|
UserTeamRed = "red"
|
||||||
@ -384,10 +386,13 @@ type WordCard struct {
|
|||||||
|
|
||||||
// table: settings
|
// table: settings
|
||||||
type GameSettings struct {
|
type GameSettings struct {
|
||||||
|
ID uint32 `json:"id" db:"id"`
|
||||||
|
RoomID string `db:"room_id"`
|
||||||
Language string `json:"language" example:"en" form:"language" db:"language"`
|
Language string `json:"language" example:"en" form:"language" db:"language"`
|
||||||
RoomPass string `json:"room_pass" db:"room_pass"`
|
RoomPass string `json:"room_pass" db:"room_pass"`
|
||||||
TurnSecondsLeft uint32 `db:"-"`
|
TurnSecondsLeft uint32 `db:"-"`
|
||||||
RoundTime uint32 `json:"round_time" db:"round_time"`
|
RoundTime uint32 `json:"round_time" db:"turn_time"`
|
||||||
|
CreatedAt time.Time `db:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// =====
|
// =====
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"gralias/models"
|
"gralias/models"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ActionsRepo interface {
|
type ActionsRepo interface {
|
||||||
@ -15,7 +17,7 @@ type ActionsRepo interface {
|
|||||||
|
|
||||||
func (p *RepoProvider) ListActions(ctx context.Context, roomID string) ([]models.Action, error) {
|
func (p *RepoProvider) ListActions(ctx context.Context, roomID string) ([]models.Action, error) {
|
||||||
actions := []models.Action{}
|
actions := []models.Action{}
|
||||||
err := p.DB.SelectContext(ctx, &actions, `SELECT actor, actor_color, action_type, word, word_color, number_associated, created_at FROM actions WHERE room_id = ? ORDER BY created_at ASC`, roomID)
|
err := sqlx.SelectContext(ctx, p.DB, &actions, `SELECT actor, actor_color, action_type, word, word_color, number_associated, created_at FROM actions WHERE room_id = ? ORDER BY created_at ASC`, roomID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -26,13 +28,14 @@ func (p *RepoProvider) ListActions(ctx context.Context, roomID string) ([]models
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) CreateAction(ctx context.Context, roomID string, a *models.Action) error {
|
func (p *RepoProvider) CreateAction(ctx context.Context, roomID string, a *models.Action) error {
|
||||||
_, err := p.DB.ExecContext(ctx, `INSERT INTO actions (room_id, actor, actor_color, action_type, word, word_color, number_associated, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, roomID, a.Actor, a.ActorColor, a.Action, a.Word, a.WordColor, a.Number, a.CreatedAt.UnixNano())
|
db := getDB(ctx, p.DB)
|
||||||
|
_, err := db.ExecContext(ctx, `INSERT INTO actions (room_id, actor, actor_color, action_type, word, word_color, number_associated, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, roomID, a.Actor, a.ActorColor, a.Action, a.Word, a.WordColor, a.Number, a.CreatedAt.UnixNano())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) GetLastClue(ctx context.Context, roomID string) (*models.Action, error) {
|
func (p *RepoProvider) GetLastClue(ctx context.Context, roomID string) (*models.Action, error) {
|
||||||
action := &models.Action{}
|
action := &models.Action{}
|
||||||
err := p.DB.GetContext(ctx, action, `SELECT actor, actor_color, action_type, word, word_color, number_associated, created_at FROM actions WHERE room_id = ? AND action_type = 'gave_clue' ORDER BY created_at DESC LIMIT 1`, roomID)
|
err := sqlx.GetContext(ctx, p.DB, action, `SELECT actor, actor_color, action_type, word, word_color, number_associated, created_at FROM actions WHERE room_id = ? AND action_type = 'gave_clue' ORDER BY created_at DESC LIMIT 1`, roomID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -41,6 +44,7 @@ func (p *RepoProvider) GetLastClue(ctx context.Context, roomID string) (*models.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) DeleteActionsByRoomID(ctx context.Context, roomID string) error {
|
func (p *RepoProvider) DeleteActionsByRoomID(ctx context.Context, roomID string) error {
|
||||||
_, err := p.DB.ExecContext(ctx, `DELETE FROM actions WHERE room_id = ?`, roomID)
|
db := getDB(ctx, p.DB)
|
||||||
|
_, err := db.ExecContext(ctx, `DELETE FROM actions WHERE room_id = ?`, roomID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package repos
|
package repos
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
@ -12,11 +13,11 @@ type AllRepos interface {
|
|||||||
RoomsRepo
|
RoomsRepo
|
||||||
ActionsRepo
|
ActionsRepo
|
||||||
PlayersRepo
|
PlayersRepo
|
||||||
|
SessionsRepo
|
||||||
}
|
}
|
||||||
|
|
||||||
type RepoProvider struct {
|
type RepoProvider struct {
|
||||||
DB *sqlx.DB
|
DB *sqlx.DB
|
||||||
Ext sqlx.Ext
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRepoProvider(pathToDB string) *RepoProvider {
|
func NewRepoProvider(pathToDB string) *RepoProvider {
|
||||||
@ -30,3 +31,11 @@ func NewRepoProvider(pathToDB string) *RepoProvider {
|
|||||||
DB: db,
|
DB: db,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDB(ctx context.Context, db *sqlx.DB) sqlx.ExtContext {
|
||||||
|
if tx, ok := ctx.Value("tx").(*sqlx.Tx);
|
||||||
|
ok {
|
||||||
|
return tx
|
||||||
|
}
|
||||||
|
return db
|
||||||
|
}
|
||||||
|
@ -3,65 +3,72 @@ package repos
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"gralias/models"
|
"gralias/models"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PlayersRepo interface {
|
type PlayersRepo interface {
|
||||||
PlayerGetByName(username string) (*models.Player, error)
|
PlayerGetByName(ctx context.Context, username string) (*models.Player, error)
|
||||||
PlayerAdd(player *models.Player) error
|
PlayerAdd(ctx context.Context, player *models.Player) error
|
||||||
PlayerUpdate(player *models.Player) error
|
PlayerUpdate(ctx context.Context, player *models.Player) error
|
||||||
PlayerDelete(roomID, username string) error
|
PlayerDelete(ctx context.Context, roomID, username string) error
|
||||||
PlayerSetRoomID(username, roomID string) error
|
PlayerSetRoomID(ctx context.Context, username, roomID string) error
|
||||||
PlayerExitRoom(username string) error
|
PlayerExitRoom(ctx context.Context, username string) error
|
||||||
PlayerListNames() ([]string, error)
|
PlayerListNames(ctx context.Context) ([]string, error)
|
||||||
PlayerList(isBot bool) ([]models.Player, error)
|
PlayerList(ctx context.Context, isBot bool) ([]models.Player, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) PlayerListNames() ([]string, error) {
|
func (p *RepoProvider) PlayerListNames(ctx context.Context) ([]string, error) {
|
||||||
var names []string
|
var names []string
|
||||||
err := p.DB.SelectContext(context.Background(), &names, "SELECT username FROM players;")
|
err := sqlx.SelectContext(ctx, p.DB, &names, "SELECT username FROM players;")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return names, nil
|
return names, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) PlayerGetByName(username string) (*models.Player, error) {
|
func (p *RepoProvider) PlayerGetByName(ctx context.Context, username string) (*models.Player, error) {
|
||||||
var player models.Player
|
var player models.Player
|
||||||
err := p.DB.GetContext(context.Background(), &player, "SELECT id, room_id, username, team, role, is_bot FROM players WHERE username = ?", username)
|
err := sqlx.GetContext(ctx, p.DB, &player, "SELECT id, room_id, username, team, role, is_bot FROM players WHERE username = ?", username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &player, nil
|
return &player, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) PlayerAdd(player *models.Player) error {
|
func (p *RepoProvider) PlayerAdd(ctx context.Context, player *models.Player) error {
|
||||||
_, err := p.DB.ExecContext(context.Background(), "INSERT INTO players (room_id, username, team, role, is_bot) VALUES (?, ?, ?, ?, ?)",
|
db := getDB(ctx, p.DB)
|
||||||
|
_, err := db.ExecContext(ctx, "INSERT INTO players (room_id, username, team, role, is_bot) VALUES (?, ?, ?, ?, ?)",
|
||||||
player.RoomID, player.Username, player.Team, player.Role, player.IsBot)
|
player.RoomID, player.Username, player.Team, player.Role, player.IsBot)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) PlayerUpdate(player *models.Player) error {
|
func (p *RepoProvider) PlayerUpdate(ctx context.Context, player *models.Player) error {
|
||||||
_, err := p.DB.ExecContext(context.Background(), "UPDATE players SET room_id = ?, username = ?, team = ?, role = ?, is_bot = ? WHERE id = ?",
|
db := getDB(ctx, p.DB)
|
||||||
|
_, err := db.ExecContext(ctx, "UPDATE players SET room_id = ?, username = ?, team = ?, role = ?, is_bot = ? WHERE id = ?",
|
||||||
player.RoomID, player.Username, player.Team, player.Role, player.IsBot, player.ID)
|
player.RoomID, player.Username, player.Team, player.Role, player.IsBot, player.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) PlayerDelete(roomID, username string) error {
|
func (p *RepoProvider) PlayerDelete(ctx context.Context, roomID, username string) error {
|
||||||
_, err := p.DB.ExecContext(context.Background(), "DELETE FROM players WHERE room_id = ? AND username = ?", roomID, username)
|
db := getDB(ctx, p.DB)
|
||||||
|
_, err := db.ExecContext(ctx, "DELETE FROM players WHERE room_id = ? AND username = ?", roomID, username)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) PlayerSetRoomID(username, roomID string) error {
|
func (p *RepoProvider) PlayerSetRoomID(ctx context.Context, username, roomID string) error {
|
||||||
_, err := p.DB.ExecContext(context.Background(), "UPDATE players SET room_id = ? WHERE username = ?", roomID, username)
|
db := getDB(ctx, p.DB)
|
||||||
|
_, err := db.ExecContext(ctx, "UPDATE players SET room_id = ? WHERE username = ?", roomID, username)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) PlayerExitRoom(username string) error {
|
func (p *RepoProvider) PlayerExitRoom(ctx context.Context, username string) error {
|
||||||
_, err := p.DB.ExecContext(context.Background(), "UPDATE players SET room_id = null WHERE username = ?", username)
|
db := getDB(ctx, p.DB)
|
||||||
|
_, err := db.ExecContext(ctx, "UPDATE players SET room_id = null WHERE username = ?", username)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) PlayerList(isBot bool) ([]models.Player, error) {
|
func (p *RepoProvider) PlayerList(ctx context.Context, isBot bool) ([]models.Player, error) {
|
||||||
var players []models.Player
|
var players []models.Player
|
||||||
var query string
|
var query string
|
||||||
if isBot {
|
if isBot {
|
||||||
@ -69,7 +76,7 @@ func (p *RepoProvider) PlayerList(isBot bool) ([]models.Player, error) {
|
|||||||
} else {
|
} else {
|
||||||
query = "SELECT id, room_id, username, team, role, is_bot FROM players WHERE is_bot = false;"
|
query = "SELECT id, room_id, username, team, role, is_bot FROM players WHERE is_bot = false;"
|
||||||
}
|
}
|
||||||
err := p.DB.SelectContext(context.Background(), &players, query)
|
err := sqlx.SelectContext(ctx, p.DB, &players, query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package repos
|
package repos
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"gralias/models"
|
"gralias/models"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -45,7 +46,7 @@ func TestPlayersRepo_AddPlayer(t *testing.T) {
|
|||||||
IsBot: false,
|
IsBot: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := repo.AddPlayer(player)
|
err := repo.PlayerAdd(context.Background(), player)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
var retrievedPlayer models.Player
|
var retrievedPlayer models.Player
|
||||||
@ -71,7 +72,7 @@ func TestPlayersRepo_GetPlayer(t *testing.T) {
|
|||||||
_, err := db.Exec(`INSERT INTO players (room_id, username, team, role, is_bot) VALUES (?, ?, ?, ?, ?)`, player.RoomID, player.Username, player.Team, player.Role, player.IsBot)
|
_, err := db.Exec(`INSERT INTO players (room_id, username, team, role, is_bot) VALUES (?, ?, ?, ?, ?)`, player.RoomID, player.Username, player.Team, player.Role, player.IsBot)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
retrievedPlayer, err := repo.GetPlayer(player.RoomID, player.Username)
|
retrievedPlayer, err := repo.PlayerGetByName(context.Background(), player.Username)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, retrievedPlayer)
|
assert.NotNil(t, retrievedPlayer)
|
||||||
assert.Equal(t, player.Username, retrievedPlayer.Username)
|
assert.Equal(t, player.Username, retrievedPlayer.Username)
|
||||||
@ -94,7 +95,7 @@ func TestPlayersRepo_DeletePlayer(t *testing.T) {
|
|||||||
_, err := db.Exec(`INSERT INTO players (room_id, username, team, role, is_bot) VALUES (?, ?, ?, ?, ?)`, player.RoomID, player.Username, player.Team, player.Role, player.IsBot)
|
_, err := db.Exec(`INSERT INTO players (room_id, username, team, role, is_bot) VALUES (?, ?, ?, ?, ?)`, player.RoomID, player.Username, player.Team, player.Role, player.IsBot)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = repo.DeletePlayer(player.RoomID, player.Username)
|
err = repo.PlayerDelete(context.Background(), player.RoomID, player.Username)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
var count int
|
var count int
|
||||||
|
@ -3,6 +3,8 @@ package repos
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"gralias/models"
|
"gralias/models"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RoomsRepo interface {
|
type RoomsRepo interface {
|
||||||
@ -16,7 +18,7 @@ type RoomsRepo interface {
|
|||||||
|
|
||||||
func (p *RepoProvider) RoomList(ctx context.Context) ([]*models.Room, error) {
|
func (p *RepoProvider) RoomList(ctx context.Context) ([]*models.Room, error) {
|
||||||
rooms := []*models.Room{}
|
rooms := []*models.Room{}
|
||||||
err := p.DB.SelectContext(ctx, &rooms, `SELECT * FROM rooms`)
|
err := sqlx.SelectContext(ctx, p.DB, &rooms, `SELECT * FROM rooms`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -25,37 +27,58 @@ func (p *RepoProvider) RoomList(ctx context.Context) ([]*models.Room, error) {
|
|||||||
|
|
||||||
func (p *RepoProvider) RoomGetByID(ctx context.Context, id string) (*models.Room, error) {
|
func (p *RepoProvider) RoomGetByID(ctx context.Context, id string) (*models.Room, error) {
|
||||||
room := &models.Room{}
|
room := &models.Room{}
|
||||||
err := p.DB.GetContext(ctx, room, `SELECT * FROM rooms WHERE id = ?`, id)
|
err := sqlx.GetContext(ctx, p.DB, room, `SELECT * FROM rooms WHERE id = ?`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
settings := &models.GameSettings{}
|
||||||
|
err = sqlx.GetContext(ctx, p.DB, settings, `SELECT * FROM settings WHERE room_id = ?`, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
room.Settings = *settings
|
||||||
return room, nil
|
return room, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) RoomCreate(ctx context.Context, r *models.Room) error {
|
func (p *RepoProvider) RoomCreate(ctx context.Context, r *models.Room) error {
|
||||||
_, err := p.DB.ExecContext(ctx, `INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, , is_running, is_over, team_won, room_link) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, r.ID, r.CreatedAt, r.CreatorName, r.TeamTurn, r.ThisTurnLimit, r.OpenedThisTurn, r.BlueCounter, r.RedCounter, r.RedTurn, r.MimeDone, r.IsRunning, r.IsOver, r.TeamWon, r.RoomLink)
|
db := getDB(ctx, p.DB)
|
||||||
|
_, err := db.ExecContext(ctx, `INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_running, is_over, team_won, room_link) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, r.ID, r.CreatedAt, r.CreatorName, r.TeamTurn, r.ThisTurnLimit, r.OpenedThisTurn, r.BlueCounter, r.RedCounter, r.RedTurn, r.MimeDone, r.IsRunning, r.IsOver, r.TeamWon, r.RoomLink)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = db.ExecContext(ctx, `INSERT INTO settings (room_id, language, room_pass, turn_time) VALUES (?, ?, ?, ?)`, r.ID, r.Settings.Language, r.Settings.RoomPass, r.Settings.RoundTime)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) RoomDeleteByID(ctx context.Context, id string) error {
|
func (p *RepoProvider) RoomDeleteByID(ctx context.Context, id string) error {
|
||||||
_, err := p.DB.ExecContext(ctx, `DELETE FROM rooms WHERE id = ?`, id)
|
db := getDB(ctx, p.DB)
|
||||||
|
_, err := db.ExecContext(ctx, `DELETE FROM rooms WHERE id = ?`, id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = db.ExecContext(ctx, `DELETE FROM settings WHERE room_id = ?`, id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) RoomUpdate(ctx context.Context, r *models.Room) error {
|
func (p *RepoProvider) RoomUpdate(ctx context.Context, r *models.Room) error {
|
||||||
_, err := p.DB.ExecContext(ctx, `UPDATE rooms SET team_turn = ?, this_turn_limit = ?, opened_this_turn = ?, blue_counter = ?, red_counter = ?, red_turn = ?, mime_done = ?, = ?, is_running = ?, is_over = ?, team_won = ?, room_link = ? WHERE id = ?`, r.TeamTurn, r.ThisTurnLimit, r.OpenedThisTurn, r.BlueCounter, r.RedCounter, r.RedTurn, r.MimeDone, r.IsRunning, r.IsOver, r.TeamWon, r.RoomLink, r.ID)
|
db := getDB(ctx, p.DB)
|
||||||
|
_, err := db.ExecContext(ctx, `UPDATE rooms SET team_turn = ?, this_turn_limit = ?, opened_this_turn = ?, blue_counter = ?, red_counter = ?, red_turn = ?, mime_done = ?, is_running = ?, is_over = ?, team_won = ?, room_link = ? WHERE id = ?`, r.TeamTurn, r.ThisTurnLimit, r.OpenedThisTurn, r.BlueCounter, r.RedCounter, r.RedTurn, r.MimeDone, r.IsRunning, r.IsOver, r.TeamWon, r.RoomLink, r.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = db.ExecContext(ctx, `UPDATE settings SET language = ?, room_pass = ?, turn_time = ? WHERE room_id = ?`, r.Settings.Language, r.Settings.RoomPass, r.Settings.RoundTime, r.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) RoomGetExtended(ctx context.Context, id string) (*models.Room, error) {
|
func (p *RepoProvider) RoomGetExtended(ctx context.Context, id string) (*models.Room, error) {
|
||||||
room := &models.Room{}
|
room := &models.Room{}
|
||||||
err := p.DB.GetContext(ctx, room, `SELECT * FROM rooms WHERE id = ?`, id)
|
err := sqlx.GetContext(ctx, p.DB, room, `SELECT * FROM rooms WHERE id = ?`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Get players
|
// Get players
|
||||||
players := []*models.Player{}
|
players := []*models.Player{}
|
||||||
err = p.DB.SelectContext(ctx, &players, `SELECT * FROM players WHERE room_id = ?`, id)
|
err = sqlx.SelectContext(ctx, p.DB, &players, `SELECT * FROM players WHERE room_id = ?`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -87,21 +110,21 @@ func (p *RepoProvider) RoomGetExtended(ctx context.Context, id string) (*models.
|
|||||||
}
|
}
|
||||||
// Get word cards
|
// Get word cards
|
||||||
wordCards := []models.WordCard{}
|
wordCards := []models.WordCard{}
|
||||||
err = p.DB.SelectContext(ctx, &wordCards, `SELECT * FROM word_cards WHERE room_id = ?`, id)
|
err = sqlx.SelectContext(ctx, p.DB, &wordCards, `SELECT * FROM word_cards WHERE room_id = ?`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
room.Cards = wordCards
|
room.Cards = wordCards
|
||||||
// Get actions
|
// Get actions
|
||||||
actions := []models.Action{}
|
actions := []models.Action{}
|
||||||
err = p.DB.SelectContext(ctx, &actions, `SELECT * FROM actions WHERE room_id = ? ORDER BY created_at ASC`, id)
|
err = sqlx.SelectContext(ctx, p.DB, &actions, `SELECT * FROM actions WHERE room_id = ? ORDER BY created_at ASC`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
room.ActionHistory = actions
|
room.ActionHistory = actions
|
||||||
// Get settings
|
// Get settings
|
||||||
settings := &models.GameSettings{}
|
settings := &models.GameSettings{}
|
||||||
err = p.DB.GetContext(ctx, settings, `SELECT * FROM settings WHERE room_id = ?`, id)
|
err = sqlx.GetContext(ctx, p.DB, settings, `SELECT * FROM settings WHERE room_id = ?`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -18,22 +18,29 @@ func setupTestDB(t *testing.T) (*sqlx.DB, func()) {
|
|||||||
schema := `
|
schema := `
|
||||||
CREATE TABLE IF NOT EXISTS rooms (
|
CREATE TABLE IF NOT EXISTS rooms (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
created_at DATETIME,
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
creator_name TEXT,
|
creator_name TEXT NOT NULL,
|
||||||
team_turn TEXT,
|
team_turn TEXT NOT NULL DEFAULT '',
|
||||||
this_turn_limit INTEGER,
|
this_turn_limit INTEGER NOT NULL DEFAULT 0,
|
||||||
opened_this_turn INTEGER,
|
opened_this_turn INTEGER NOT NULL DEFAULT 0,
|
||||||
blue_counter INTEGER,
|
blue_counter INTEGER NOT NULL DEFAULT 0,
|
||||||
red_counter INTEGER,
|
red_counter INTEGER NOT NULL DEFAULT 0,
|
||||||
red_turn BOOLEAN,
|
red_turn BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
mime_done BOOLEAN,
|
mime_done BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
is_public BOOLEAN,
|
is_running BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
is_running BOOLEAN,
|
is_over BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
language TEXT,
|
team_won TEXT NOT NULL DEFAULT '',
|
||||||
round_time INTEGER,
|
room_link TEXT NOT NULL DEFAULT ''
|
||||||
is_over BOOLEAN,
|
);
|
||||||
team_won TEXT,
|
|
||||||
room_pass TEXT
|
CREATE TABLE IF NOT EXISTS settings (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
room_id TEXT NOT NULL,
|
||||||
|
language TEXT NOT NULL DEFAULT 'en',
|
||||||
|
room_pass TEXT NOT NULL DEFAULT '',
|
||||||
|
turn_time INTEGER NOT NULL DEFAULT 60,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (room_id) REFERENCES rooms(id)
|
||||||
);
|
);
|
||||||
`
|
`
|
||||||
_, err = db.Exec(schema)
|
_, err = db.Exec(schema)
|
||||||
@ -61,16 +68,18 @@ func TestRoomsRepo_CreateRoom(t *testing.T) {
|
|||||||
RedCounter: 0,
|
RedCounter: 0,
|
||||||
RedTurn: false,
|
RedTurn: false,
|
||||||
MimeDone: false,
|
MimeDone: false,
|
||||||
IsPublic: true,
|
|
||||||
IsRunning: false,
|
IsRunning: false,
|
||||||
Language: "en",
|
|
||||||
RoundTime: 60,
|
|
||||||
IsOver: false,
|
IsOver: false,
|
||||||
TeamWon: "",
|
TeamWon: "",
|
||||||
|
RoomLink: "",
|
||||||
|
Settings: models.GameSettings{
|
||||||
|
Language: "en",
|
||||||
|
RoundTime: 60,
|
||||||
RoomPass: "",
|
RoomPass: "",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := repo.CreateRoom(context.Background(), room)
|
err := repo.RoomCreate(context.Background(), room)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// Verify the room was created
|
// Verify the room was created
|
||||||
@ -79,6 +88,13 @@ func TestRoomsRepo_CreateRoom(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, room.ID, retrievedRoom.ID)
|
assert.Equal(t, room.ID, retrievedRoom.ID)
|
||||||
assert.Equal(t, room.CreatorName, retrievedRoom.CreatorName)
|
assert.Equal(t, room.CreatorName, retrievedRoom.CreatorName)
|
||||||
|
|
||||||
|
var retrievedSettings models.GameSettings
|
||||||
|
err = db.Get(&retrievedSettings, "SELECT id, language, room_pass, turn_time FROM settings WHERE room_id = ?", room.ID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, room.Settings.Language, retrievedSettings.Language)
|
||||||
|
assert.Equal(t, room.Settings.RoundTime, retrievedSettings.RoundTime)
|
||||||
|
assert.Equal(t, room.Settings.RoomPass, retrievedSettings.RoomPass)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRoomsRepo_GetRoomByID(t *testing.T) {
|
func TestRoomsRepo_GetRoomByID(t *testing.T) {
|
||||||
@ -98,24 +114,29 @@ func TestRoomsRepo_GetRoomByID(t *testing.T) {
|
|||||||
RedCounter: 0,
|
RedCounter: 0,
|
||||||
RedTurn: true,
|
RedTurn: true,
|
||||||
MimeDone: false,
|
MimeDone: false,
|
||||||
IsPublic: true,
|
|
||||||
IsRunning: false,
|
IsRunning: false,
|
||||||
Language: "en",
|
|
||||||
RoundTime: 60,
|
|
||||||
IsOver: false,
|
IsOver: false,
|
||||||
TeamWon: "",
|
TeamWon: "",
|
||||||
|
RoomLink: "",
|
||||||
|
Settings: models.GameSettings{
|
||||||
|
Language: "en",
|
||||||
|
RoundTime: 60,
|
||||||
RoomPass: "",
|
RoomPass: "",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert a room directly into the database for testing GetRoomByID
|
// Insert a room directly into the database for testing GetRoomByID
|
||||||
_, err := db.Exec(`INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_public, is_running, language, round_time, is_over, team_won, room_pass) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, room.ID, room.CreatedAt, room.CreatorName, room.TeamTurn, room.ThisTurnLimit, room.OpenedThisTurn, room.BlueCounter, room.RedCounter, room.RedTurn, room.MimeDone, room.IsPublic, room.IsRunning, room.Language, room.RoundTime, room.IsOver, room.TeamWon, room.RoomPass)
|
_, err := db.Exec(`INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_running, is_over, team_won, room_link) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, room.ID, room.CreatedAt, room.CreatorName, room.TeamTurn, room.ThisTurnLimit, room.OpenedThisTurn, room.BlueCounter, room.RedCounter, room.RedTurn, room.MimeDone, room.IsRunning, room.IsOver, room.TeamWon, room.RoomLink)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, err = db.Exec(`INSERT INTO settings (room_id, language, room_pass, turn_time) VALUES (?, ?, ?, ?)`, room.ID, room.Settings.Language, room.Settings.RoomPass, room.Settings.RoundTime)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
retrievedRoom, err := repo.GetRoomByID(context.Background(), room.ID)
|
retrievedRoom, err := repo.RoomGetByID(context.Background(), room.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, retrievedRoom)
|
assert.NotNil(t, retrievedRoom)
|
||||||
assert.Equal(t, room.ID, retrievedRoom.ID)
|
assert.Equal(t, room.ID, retrievedRoom.ID)
|
||||||
assert.Equal(t, room.CreatorName, retrievedRoom.CreatorName)
|
assert.Equal(t, room.CreatorName, retrievedRoom.CreatorName)
|
||||||
|
assert.Equal(t, room.Settings.Language, retrievedRoom.Settings.Language)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRoomsRepo_ListRooms(t *testing.T) {
|
func TestRoomsRepo_ListRooms(t *testing.T) {
|
||||||
@ -135,13 +156,15 @@ func TestRoomsRepo_ListRooms(t *testing.T) {
|
|||||||
RedCounter: 0,
|
RedCounter: 0,
|
||||||
RedTurn: false,
|
RedTurn: false,
|
||||||
MimeDone: false,
|
MimeDone: false,
|
||||||
IsPublic: true,
|
|
||||||
IsRunning: false,
|
IsRunning: false,
|
||||||
Language: "en",
|
|
||||||
RoundTime: 60,
|
|
||||||
IsOver: false,
|
IsOver: false,
|
||||||
TeamWon: "",
|
TeamWon: "",
|
||||||
|
RoomLink: "",
|
||||||
|
Settings: models.GameSettings{
|
||||||
|
Language: "en",
|
||||||
|
RoundTime: 60,
|
||||||
RoomPass: "",
|
RoomPass: "",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
room2 := &models.Room{
|
room2 := &models.Room{
|
||||||
ID: "list_room_2",
|
ID: "list_room_2",
|
||||||
@ -154,21 +177,28 @@ func TestRoomsRepo_ListRooms(t *testing.T) {
|
|||||||
RedCounter: 0,
|
RedCounter: 0,
|
||||||
RedTurn: true,
|
RedTurn: true,
|
||||||
MimeDone: false,
|
MimeDone: false,
|
||||||
IsPublic: true,
|
|
||||||
IsRunning: false,
|
IsRunning: false,
|
||||||
Language: "en",
|
|
||||||
RoundTime: 60,
|
|
||||||
IsOver: false,
|
IsOver: false,
|
||||||
TeamWon: "",
|
TeamWon: "",
|
||||||
|
RoomLink: "",
|
||||||
|
Settings: models.GameSettings{
|
||||||
|
Language: "en",
|
||||||
|
RoundTime: 60,
|
||||||
RoomPass: "",
|
RoomPass: "",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := db.Exec(`INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_public, is_running, language, round_time, is_over, team_won, room_pass) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, room1.ID, room1.CreatedAt, room1.CreatorName, room1.TeamTurn, room1.ThisTurnLimit, room1.OpenedThisTurn, room1.BlueCounter, room1.RedCounter, room1.RedTurn, room1.MimeDone, room1.IsPublic, room1.IsRunning, room1.Language, room1.RoundTime, room1.IsOver, room1.TeamWon, room1.RoomPass)
|
_, err := db.Exec(`INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_running, is_over, team_won, room_link) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, room1.ID, room1.CreatedAt, room1.CreatorName, room1.TeamTurn, room1.ThisTurnLimit, room1.OpenedThisTurn, room1.BlueCounter, room1.RedCounter, room1.RedTurn, room1.MimeDone, room1.IsRunning, room1.IsOver, room1.TeamWon, room1.RoomLink)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
_, err = db.Exec(`INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_public, is_running, language, round_time, is_over, team_won, room_pass) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, room2.ID, room2.CreatedAt, room2.CreatorName, room2.TeamTurn, room2.ThisTurnLimit, room2.OpenedThisTurn, room2.BlueCounter, room2.RedCounter, room2.RedTurn, room2.MimeDone, room2.IsPublic, room2.IsRunning, room2.Language, room2.RoundTime, room2.IsOver, room2.TeamWon, room2.RoomPass)
|
_, err = db.Exec(`INSERT INTO settings (room_id, language, room_pass, turn_time) VALUES (?, ?, ?, ?)`, room1.ID, room1.Settings.Language, room1.Settings.RoomPass, room1.Settings.RoundTime)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
rooms, err := repo.ListRooms(context.Background())
|
_, err = db.Exec(`INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_running, is_over, team_won, room_link) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, room2.ID, room2.CreatedAt, room2.CreatorName, room2.TeamTurn, room2.ThisTurnLimit, room2.OpenedThisTurn, room2.BlueCounter, room2.RedCounter, room2.RedTurn, room2.MimeDone, room2.IsRunning, room2.IsOver, room2.TeamWon, room2.RoomLink)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, err = db.Exec(`INSERT INTO settings (room_id, language, room_pass, turn_time) VALUES (?, ?, ?, ?)`, room2.ID, room2.Settings.Language, room2.Settings.RoomPass, room2.Settings.RoundTime)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
rooms, err := repo.RoomList(context.Background())
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, rooms, 2)
|
assert.Len(t, rooms, 2)
|
||||||
}
|
}
|
||||||
@ -190,25 +220,33 @@ func TestRoomsRepo_DeleteRoomByID(t *testing.T) {
|
|||||||
RedCounter: 0,
|
RedCounter: 0,
|
||||||
RedTurn: false,
|
RedTurn: false,
|
||||||
MimeDone: false,
|
MimeDone: false,
|
||||||
IsPublic: true,
|
|
||||||
IsRunning: false,
|
IsRunning: false,
|
||||||
Language: "en",
|
|
||||||
RoundTime: 60,
|
|
||||||
IsOver: false,
|
IsOver: false,
|
||||||
TeamWon: "",
|
TeamWon: "",
|
||||||
|
RoomLink: "",
|
||||||
|
Settings: models.GameSettings{
|
||||||
|
Language: "en",
|
||||||
|
RoundTime: 60,
|
||||||
RoomPass: "",
|
RoomPass: "",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := db.Exec(`INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_public, is_running, language, round_time, is_over, team_won, room_pass) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, room.ID, room.CreatedAt, room.CreatorName, room.TeamTurn, room.ThisTurnLimit, room.OpenedThisTurn, room.BlueCounter, room.RedCounter, room.RedTurn, room.MimeDone, room.IsPublic, room.IsRunning, room.Language, room.RoundTime, room.IsOver, room.TeamWon, room.RoomPass)
|
_, err := db.Exec(`INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_running, is_over, team_won, room_link) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, room.ID, room.CreatedAt, room.CreatorName, room.TeamTurn, room.ThisTurnLimit, room.OpenedThisTurn, room.BlueCounter, room.RedCounter, room.RedTurn, room.MimeDone, room.IsRunning, room.IsOver, room.TeamWon, room.RoomLink)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, err = db.Exec(`INSERT INTO settings (room_id, language, room_pass, turn_time) VALUES (?, ?, ?, ?)`, room.ID, room.Settings.Language, room.Settings.RoomPass, room.Settings.RoundTime)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = repo.DeleteRoomByID(context.Background(), room.ID)
|
err = repo.RoomDeleteByID(context.Background(), room.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
var count int
|
var count int
|
||||||
err = db.Get(&count, "SELECT COUNT(*) FROM rooms WHERE id = ?", room.ID)
|
err = db.Get(&count, "SELECT COUNT(*) FROM rooms WHERE id = ?", room.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 0, count)
|
assert.Equal(t, 0, count)
|
||||||
|
|
||||||
|
err = db.Get(&count, "SELECT COUNT(*) FROM settings WHERE room_id = ?", room.ID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 0, count)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRoomsRepo_UpdateRoom(t *testing.T) {
|
func TestRoomsRepo_UpdateRoom(t *testing.T) {
|
||||||
@ -228,22 +266,27 @@ func TestRoomsRepo_UpdateRoom(t *testing.T) {
|
|||||||
RedCounter: 0,
|
RedCounter: 0,
|
||||||
RedTurn: false,
|
RedTurn: false,
|
||||||
MimeDone: false,
|
MimeDone: false,
|
||||||
IsPublic: true,
|
|
||||||
IsRunning: false,
|
IsRunning: false,
|
||||||
Language: "en",
|
|
||||||
RoundTime: 60,
|
|
||||||
IsOver: false,
|
IsOver: false,
|
||||||
TeamWon: "",
|
TeamWon: "",
|
||||||
|
RoomLink: "",
|
||||||
|
Settings: models.GameSettings{
|
||||||
|
Language: "en",
|
||||||
|
RoundTime: 60,
|
||||||
RoomPass: "",
|
RoomPass: "",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := db.Exec(`INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_public, is_running, language, round_time, is_over, team_won, room_pass) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, room.ID, room.CreatedAt, room.CreatorName, room.TeamTurn, room.ThisTurnLimit, room.OpenedThisTurn, room.BlueCounter, room.RedCounter, room.RedTurn, room.MimeDone, room.IsPublic, room.IsRunning, room.Language, room.RoundTime, room.IsOver, room.TeamWon, room.RoomPass)
|
_, err := db.Exec(`INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_running, is_over, team_won, room_link) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, room.ID, room.CreatedAt, room.CreatorName, room.TeamTurn, room.ThisTurnLimit, room.OpenedThisTurn, room.BlueCounter, room.RedCounter, room.RedTurn, room.MimeDone, room.IsRunning, room.IsOver, room.TeamWon, room.RoomLink)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, err = db.Exec(`INSERT INTO settings (room_id, language, room_pass, turn_time) VALUES (?, ?, ?, ?)`, room.ID, room.Settings.Language, room.Settings.RoomPass, room.Settings.RoundTime)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
room.TeamTurn = "red"
|
room.TeamTurn = "red"
|
||||||
room.BlueCounter = 10
|
room.BlueCounter = 10
|
||||||
|
room.Settings.RoundTime = 120
|
||||||
|
|
||||||
err = repo.UpdateRoom(context.Background(), room)
|
err = repo.RoomUpdate(context.Background(), room)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
var updatedRoom models.Room
|
var updatedRoom models.Room
|
||||||
@ -251,4 +294,9 @@ func TestRoomsRepo_UpdateRoom(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, models.UserTeam("red"), updatedRoom.TeamTurn)
|
assert.Equal(t, models.UserTeam("red"), updatedRoom.TeamTurn)
|
||||||
assert.Equal(t, uint8(10), updatedRoom.BlueCounter)
|
assert.Equal(t, uint8(10), updatedRoom.BlueCounter)
|
||||||
|
|
||||||
|
var updatedSettings models.GameSettings
|
||||||
|
err = db.Get(&updatedSettings, "SELECT * FROM settings WHERE room_id = ?", room.ID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, uint32(120), updatedSettings.RoundTime)
|
||||||
}
|
}
|
@ -16,9 +16,10 @@ type SessionsRepo interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) SessionByToken(ctx context.Context, token string) (*models.Session, error) {
|
func (p *RepoProvider) SessionByToken(ctx context.Context, token string) (*models.Session, error) {
|
||||||
|
db := getDB(ctx, p.DB)
|
||||||
session := &models.Session{}
|
session := &models.Session{}
|
||||||
// The lifetime in the DB is in seconds, but in the model it is in minutes.
|
// The lifetime in the DB is in seconds, but in the model it is in minutes.
|
||||||
err := p.DB.GetContext(ctx, session, `SELECT id, updated_at, lifetime / 60 as lifetime, cookie_token, username FROM sessions WHERE cookie_token = ?`, token)
|
err := sqlx.GetContext(ctx, db, session, `SELECT id, updated_at, lifetime / 60 as lifetime, cookie_token, username FROM sessions WHERE cookie_token = ?`, token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -26,36 +27,23 @@ func (p *RepoProvider) SessionByToken(ctx context.Context, token string) (*model
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) SessionCreate(ctx context.Context, session *models.Session) error {
|
func (p *RepoProvider) SessionCreate(ctx context.Context, session *models.Session) error {
|
||||||
p.Ext = p.DB
|
db := getDB(ctx, p.DB)
|
||||||
tx, ok := ctx.Value("sqltx").(*sqlx.Tx)
|
|
||||||
if ok && tx != nil {
|
|
||||||
// how to know if it is a final exec in chain?
|
|
||||||
// or is it better to commit outside?
|
|
||||||
tocommit, ok := ctx.Value("tocommit").(bool)
|
|
||||||
if ok && tocommit {
|
|
||||||
defer func() {
|
|
||||||
if err := tx.Commit(); err != nil {
|
|
||||||
// log
|
|
||||||
// return err
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
p.Ext = tx
|
|
||||||
}
|
|
||||||
// The lifetime in the model is in minutes, but in the DB it is in seconds.
|
// The lifetime in the model is in minutes, but in the DB it is in seconds.
|
||||||
_, err := p.Ext.Exec(`INSERT INTO sessions (updated_at, lifetime, cookie_token, username) VALUES (?, ?, ?, ?)`,
|
_, err := db.ExecContext(ctx, `INSERT INTO sessions (updated_at, lifetime, cookie_token, username) VALUES (?, ?, ?, ?)`,
|
||||||
time.Now(), session.Lifetime*60, session.CookieToken, session.Username)
|
time.Now(), session.Lifetime*60, session.CookieToken, session.Username)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) SessionUpdate(ctx context.Context, session *models.Session) error {
|
func (p *RepoProvider) SessionUpdate(ctx context.Context, session *models.Session) error {
|
||||||
|
db := getDB(ctx, p.DB)
|
||||||
// The lifetime in the model is in minutes, but in the DB it is in seconds.
|
// The lifetime in the model is in minutes, but in the DB it is in seconds.
|
||||||
_, err := p.DB.ExecContext(ctx, `UPDATE sessions SET updated_at = ?, lifetime = ? WHERE cookie_token = ?`,
|
_, err := db.ExecContext(ctx, `UPDATE sessions SET updated_at = ?, lifetime = ? WHERE cookie_token = ?`,
|
||||||
time.Now(), session.Lifetime*60, session.CookieToken)
|
time.Now(), session.Lifetime*60, session.CookieToken)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) SessionDelete(ctx context.Context, token string) error {
|
func (p *RepoProvider) SessionDelete(ctx context.Context, token string) error {
|
||||||
_, err := p.DB.ExecContext(ctx, `DELETE FROM sessions WHERE cookie_token = ?`, token)
|
db := getDB(ctx, p.DB)
|
||||||
|
_, err := db.ExecContext(ctx, `DELETE FROM sessions WHERE cookie_token = ?`, token)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
1
todos.md
1
todos.md
@ -1,4 +1,5 @@
|
|||||||
### feats
|
### feats
|
||||||
|
- implement transactional pattern in db write methods; +
|
||||||
- implement the db methods for sessions in repos/session.go; +
|
- implement the db methods for sessions in repos/session.go; +
|
||||||
- auto close room if nothing is going on there (hmm) for ~1h; +
|
- auto close room if nothing is going on there (hmm) for ~1h; +
|
||||||
- words database (file) load and form random 25 words; +
|
- words database (file) load and form random 25 words; +
|
||||||
|
Reference in New Issue
Block a user