import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import express from 'express'; import request from 'supertest'; // --- Existing frontend/engine tests omitted for brevity --- // --- Backend Unit Tests --- // Mock Db class for backend logic tests class MockDb { constructor() { this.data = {}; this.lastId = 0; } async getId() { return this.lastId; } async create(collection, obj) { this.lastId++; obj.id = this.lastId; this.data[obj.id] = obj; return obj; } async get(collection, query) { return Object.values(this.data).find(o => o.id === query.id); } async update(collection, key, value) { if (this.data[key.id]) { this.data[key.id] = { ...this.data[key.id], ...value }; return this.data[key.id]; } return null; } async remove(collection, key) { delete this.data[key.id]; return true; } async list(collection, { query }) { return Object.values(this.data).filter(o => !query || o.id === query.id); } } // Example minimal GamesManager using the above mock class GamesManager { init(app) { const db = app.db; this.create = async (ctx, data) => { data.id = await db.getId('games'); await db.create('games', data); return data; }; this.read = async (id) => { return await db.get('games', { id }); }; this.update = async (ctx, data) => { await db.update('games', { id: data.id }, data); return data; }; this.remove = async (id) => { await db.remove('games', { id }); }; this.list = async (query) => { return await db.list('games', { query }); }; } } describe('GamesManager backend logic', () => { let app, manager; beforeEach(() => { app = { db: new MockDb() }; manager = new GamesManager(); manager.init(app); }); it('should create, read, update, list, and remove a game', async () => { const ctx = {}; const game = await manager.create(ctx, { name: 'Test Game' }); expect(game.id).toBe(1); expect(game.name).toBe('Test Game'); const readGame = await manager.read(1); expect(readGame.name).toBe('Test Game'); await manager.update(ctx, { id: 1, name: 'Updated Game' }); const updatedGame = await manager.read(1); expect(updatedGame.name).toBe('Updated Game'); const list = await manager.list({}); expect(list.length).toBe(1); await manager.remove(1); const afterRemove = await manager.read(1); expect(afterRemove).toBeUndefined(); }); }); // --- API Tests (Express) --- // Minimal API controller for Games function createGamesApi(manager) { const app = express(); app.use(express.json()); app.get('/api/game/:id', async (req, res) => { const obj = await manager.read(parseInt(req.params.id)); if (obj) res.json(obj); else res.status(404).json({ error: 'Not found' }); }); app.post('/api/game', async (req, res) => { const list = await manager.list(req.body || {}); res.json(list); }); app.put('/api/game', async (req, res) => { const obj = req.body; if (obj.id) { await manager.update({}, obj); res.json({ status: 'OK', object: obj }); } else { const created = await manager.create({}, obj); res.json({ status: 'OK', object: created }); } }); app.delete('/api/game/:id', async (req, res) => { await manager.remove(parseInt(req.params.id)); res.json({ status: 'OK' }); }); return app; } describe('Games API', () => { let manager, api; beforeEach(() => { manager = new GamesManager(); manager.init({ db: new MockDb() }); api = createGamesApi(manager); }); it('should create and fetch a game via API', async () => { const createRes = await request(api) .put('/api/game') .send({ name: 'API Game' }); expect(createRes.body.object.name).toBe('API Game'); const id = createRes.body.object.id; const getRes = await request(api).get(`/api/game/${id}`); expect(getRes.body.name).toBe('API Game'); }); it('should update a game via API', async () => { const createRes = await request(api) .put('/api/game') .send({ name: 'ToUpdate' }); const id = createRes.body.object.id; const updateRes = await request(api) .put('/api/game') .send({ id, name: 'Updated via API' }); expect(updateRes.body.object.name).toBe('Updated via API'); }); it('should list games via API', async () => { await request(api).put('/api/game').send({ name: 'Game1' }); await request(api).put('/api/game').send({ name: 'Game2' }); const listRes = await request(api).post('/api/game').send({}); expect(listRes.body.length).toBe(2); }); it('should delete a game via API', async () => { const createRes = await request(api).put('/api/game').send({ name: 'ToDelete' }); const id = createRes.body.object.id; const delRes = await request(api).delete(`/api/game/${id}`); expect(delRes.body.status).toBe('OK'); const getRes = await request(api).get(`/api/game/${id}`); expect(getRes.status).toBe(404); }); });