improved test coverage

This commit is contained in:
MasterGordon 2025-09-11 15:01:29 +02:00
parent f2183f0d15
commit bce36b5ab4
6 changed files with 279 additions and 3 deletions

1
.gitignore vendored
View File

@ -28,3 +28,4 @@ temp_dbs
deploy.sh
sqlite.db
coverage

View File

@ -4,9 +4,14 @@ import { Game } from "../schema";
import {
getCurrentGame,
getGame,
getGames,
getGamesCount,
getTotalGamesPlayed,
parseGameState,
upsertGame,
upsertGameState,
} from "./gameRepository";
import { encode } from "@msgpack/msgpack";
describe("GameRepository", () => {
it("should get game by uuid", async () => {
@ -136,4 +141,115 @@ describe("GameRepository", () => {
started: started + 1,
});
});
it("should get finished games for user", async () => {
const db = getTestDb();
const started = Date.now();
await db.insert(Game).values({
uuid: "TestUuid1",
user: "TestUser",
stage: 1,
gameState: Buffer.from("ANY"),
finished: 1,
started,
});
await db.insert(Game).values({
uuid: "TestUuid2",
user: "TestUser",
stage: 2,
gameState: Buffer.from("ANY"),
finished: 0,
started: started + 1,
});
await db.insert(Game).values({
uuid: "TestUuid3",
user: "OtherUser",
stage: 1,
gameState: Buffer.from("ANY"),
finished: 1,
started: started + 2,
});
const games = await getGames(db, "TestUser");
expect(games).toHaveLength(1);
expect(games[0].uuid).toBe("TestUuid1");
});
it("should get total games played for user", async () => {
const db = getTestDb();
const started = Date.now();
await db.insert(Game).values({
uuid: "TestUuid1",
user: "TestUser",
stage: 1,
gameState: Buffer.from("ANY"),
finished: 1,
started,
});
await db.insert(Game).values({
uuid: "TestUuid2",
user: "TestUser",
stage: 2,
gameState: Buffer.from("ANY"),
finished: 0,
started: started + 1,
});
const totalGames = await getTotalGamesPlayed(db, "TestUser");
expect(totalGames).toBe(1);
});
it("should get total games played for all users", async () => {
const db = getTestDb();
const started = Date.now();
await db.insert(Game).values({
uuid: "TestUuid1",
user: "TestUser",
stage: 1,
gameState: Buffer.from("ANY"),
finished: 1,
started,
});
await db.insert(Game).values({
uuid: "TestUuid2",
user: "OtherUser",
stage: 2,
gameState: Buffer.from("ANY"),
finished: 1,
started: started + 1,
});
const totalGames = await getTotalGamesPlayed(db);
expect(totalGames).toBe(2);
});
it("should parse game state", () => {
const gameData = { test: "data", number: 42 };
const buffer = Buffer.from(encode(gameData));
const parsed = parseGameState(buffer);
expect(parsed).toEqual(gameData);
});
it("should upsert game state", async () => {
const db = getTestDb();
const serverGame = {
uuid: "TestUuid",
user: "TestUser",
stage: 1,
finished: 1,
started: Date.now(),
// Other ServerGame properties don't matter for this test
mines: [[false]],
width: 1,
height: 1,
isRevealed: [[false]],
isFlagged: [[false]],
isQuestionMark: [[false]],
minesCount: 0,
lastClick: [0, 0] as [number, number],
theme: "default" as const,
};
await upsertGameState(db, serverGame);
const game = await getGame(db, "TestUuid");
expect(game?.uuid).toBe("TestUuid");
expect(game?.user).toBe("TestUser");
expect(game?.stage).toBe(1);
});
});

View File

@ -82,7 +82,7 @@ export const upsertGameState = async (
game: ServerGame,
) => {
const { uuid, user, stage, finished, started } = game;
upsertGame(db, {
await upsertGame(db, {
uuid,
user,
stage,

View File

@ -37,4 +37,55 @@ describe("ScoreRepository", () => {
const result = await getScoreBoard(db);
expect(result).toEqual([{ stage: 10, user: "TestUser" }]);
});
it("should return empty array when no finished games exist", async () => {
const db = getTestDb();
await db.insert(User).values({
name: "TestUser2",
password: "test",
});
await db.insert(Game).values({
user: "TestUser2",
uuid: crypto.randomUUID(),
stage: 5,
gameState: Buffer.from("ANY"),
finished: 0,
started: Date.now(),
});
const result = await getScoreBoard(db);
expect(result).toEqual([]);
});
it("should handle multiple users and sort by highest stage", async () => {
const db = getTestDb();
await db.insert(User).values({
name: "User1",
password: "test",
});
await db.insert(User).values({
name: "User2",
password: "test",
});
await db.insert(Game).values({
user: "User1",
uuid: crypto.randomUUID(),
stage: 15,
gameState: Buffer.from("ANY"),
finished: 1,
started: Date.now(),
});
await db.insert(Game).values({
user: "User2",
uuid: crypto.randomUUID(),
stage: 25,
gameState: Buffer.from("ANY"),
finished: 1,
started: Date.now(),
});
const result = await getScoreBoard(db);
expect(result).toEqual([
{ stage: 25, user: "User2" },
{ stage: 15, user: "User1" }
]);
});
});

View File

@ -1,6 +1,6 @@
import { describe, it, expect } from "bun:test";
import { getTestDb } from "../database/getTestDb";
import { getUser, loginUser, registerUser } from "./userRepository";
import { getUser, getUserCount, getUserSettings, loginUser, registerUser, upsertUserSettings } from "./userRepository";
describe("UserRepository", () => {
it("should register a user", async () => {
@ -45,4 +45,72 @@ describe("UserRepository", () => {
password: undefined,
});
});
it("should throw error if password is incorrect", async () => {
const db = getTestDb();
await registerUser(db, "TestUser", "test");
expect(loginUser(db, "TestUser", "wrongpassword")).rejects.toThrow(
"Incorrect password",
);
});
it("should handle getUser for nonexistent user", async () => {
const db = getTestDb();
const user = await getUser(db, "NonexistentUser");
expect(user.name).toBeUndefined();
});
it("should get user count", async () => {
const db = getTestDb();
await registerUser(db, "TestUser1", "test");
await registerUser(db, "TestUser2", "test");
const count = await getUserCount(db);
expect(count).toBe(2);
});
it("should get default user settings", async () => {
const db = getTestDb();
const settings = await getUserSettings(db, "TestUser");
expect(settings).toEqual({
placeQuestionMark: false,
longPressOnDesktop: false,
showRevealAnimation: true,
soundEnabled: true,
});
});
it("should upsert user settings - insert", async () => {
const db = getTestDb();
const newSettings = {
placeQuestionMark: true,
longPressOnDesktop: true,
showRevealAnimation: false,
soundEnabled: false,
};
await upsertUserSettings(db, "TestUser", newSettings);
const settings = await getUserSettings(db, "TestUser");
expect(settings).toEqual(newSettings);
});
it("should upsert user settings - update", async () => {
const db = getTestDb();
const initialSettings = {
placeQuestionMark: false,
longPressOnDesktop: false,
showRevealAnimation: true,
soundEnabled: true,
};
await upsertUserSettings(db, "TestUser", initialSettings);
const updatedSettings = {
placeQuestionMark: true,
longPressOnDesktop: true,
showRevealAnimation: false,
soundEnabled: false,
};
await upsertUserSettings(db, "TestUser", updatedSettings);
const settings = await getUserSettings(db, "TestUser");
expect(settings).toEqual(updatedSettings);
});
});

View File

@ -1,5 +1,5 @@
import { describe, it, expect } from "bun:test";
import { getValue, ServerGame, serverToClientGame } from "./game";
import { getValue, isServerGame, isClientGame, ServerGame, ClientGame, serverToClientGame } from "./game";
describe("Game", () => {
it("should get value", () => {
@ -15,6 +15,46 @@ describe("Game", () => {
expect(getValue(mines, 1, 3)).toEqual(8);
});
it("should identify server game", () => {
const serverGame: ServerGame = {
theme: "default",
mines: [[false]],
minesCount: 0,
isRevealed: [[false]],
isFlagged: [[false]],
isQuestionMark: [[false]],
started: Date.now(),
finished: 0,
lastClick: [0, 0],
uuid: "test-uuid",
width: 1,
height: 1,
user: "TestUser",
stage: 1,
};
expect(isServerGame(serverGame)).toBe(true);
});
it("should identify client game", () => {
const clientGame: ClientGame = {
theme: "default",
minesCount: 0,
isRevealed: [[false]],
isFlagged: [[false]],
isQuestionMark: [[false]],
values: [[0]],
started: Date.now(),
lastClick: [0, 0],
uuid: "test-uuid",
width: 1,
height: 1,
user: "TestUser",
stage: 1,
};
expect(isClientGame(clientGame)).toBe(true);
expect(isServerGame(clientGame)).toBe(false);
});
it("should convert server to client game", () => {
const serverGame: ServerGame = {
theme: "default",