/** * Integration tests for Mini-Games API endpoints * Tests backend API endpoints for mini-games scoring */ describe('Mini-Games API Integration Tests', () => { const BASE_URL = process.env.API_BASE_URL || 'http://localhost:9082'; describe('POST /api/mini-game/complete', () => { test('should successfully record game completion', async () => { const response = await fetch(`${BASE_URL}/api/mini-game/complete`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer test-token', 'X-User-Id': 'test-user' }, body: JSON.stringify({ childId: 'child-123', gameCode: 'schulte', completionTime: 45, score: 85 }) }); const data = await response.json(); expect(response.status).toBe(200); expect(data.code).toBe(200); expect(data.data).toHaveProperty('pointsEarned'); expect(data.data).toHaveProperty('newBalance'); }); test('should handle different game types', async () => { const gameCodes = ['schulte', '1a2b', 'sudoku']; for (const gameCode of gameCodes) { const response = await fetch(`${BASE_URL}/api/mini-game/complete`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer test-token' }, body: JSON.stringify({ childId: 'child-123', gameCode: gameCode, completionTime: 60, score: 75 }) }); expect(response.status).toBe(200); } }); test('should validate required fields', async () => { const response = await fetch(`${BASE_URL}/api/mini-game/complete`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ // Missing required fields gameCode: 'schulte' }) }); expect(response.status).toBe(400); }); test('should handle invalid game code', async () => { const response = await fetch(`${BASE_URL}/api/mini-game/complete`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer test-token' }, body: JSON.stringify({ childId: 'child-123', gameCode: 'invalid-game', completionTime: 30, score: 50 }) }); expect(response.status).toBe(400); }); test('should calculate points based on score', async () => { // Test different score ranges const testCases = [ { score: 100, expectedPoints: 10 }, // High score { score: 75, expectedPoints: 7.5 }, // Medium score { score: 60, expectedPoints: 6 }, // Low score { score: 30, expectedPoints: 3 } // Minimum score ]; for (const testCase of testCases) { const response = await fetch(`${BASE_URL}/api/mini-game/complete`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer test-token' }, body: JSON.stringify({ childId: 'child-123', gameCode: 'schulte', completionTime: 60, score: testCase.score }) }); const data = await response.json(); if (response.status === 200) { expect(data.data.pointsEarned).toBeGreaterThanOrEqual(0); } } }); }); describe('POST /api/mini-game/list', () => { test('should return list of available games', async () => { const response = await fetch(`${BASE_URL}/api/mini-game/list`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer test-token' }, body: JSON.stringify({}) }); const data = await response.json(); expect(response.status).toBe(200); expect(data.code).toBe(200); expect(Array.isArray(data.data)).toBe(true); expect(data.data.length).toBeGreaterThan(0); }); test('should include game details', async () => { const response = await fetch(`${BASE_URL}/api/mini-game/list`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer test-token' }, body: JSON.stringify({}) }); const data = await response.json(); if (data.data.length > 0) { const game = data.data[0]; expect(game).toHaveProperty('code'); expect(game).toHaveProperty('name'); expect(game).toHaveProperty('basePoints'); } }); }); describe('POST /api/mini-game/:gameCode', () => { test('should return game details by code', async () => { const response = await fetch(`${BASE_URL}/api/mini-game/schulte`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer test-token' }, body: JSON.stringify({}) }); const data = await response.json(); expect(response.status).toBe(200); expect(data.code).toBe(200); expect(data.data).toHaveProperty('code', 'schulte'); }); test('should return 404 for invalid game code', async () => { const response = await fetch(`${BASE_URL}/api/mini-game/nonexistent`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer test-token' }, body: JSON.stringify({}) }); expect(response.status).toBe(404); }); }); describe('Authentication and Authorization', () => { test('should require authentication', async () => { const response = await fetch(`${BASE_URL}/api/mini-game/complete`, { method: 'POST', headers: { 'Content-Type': 'application/json' // No Authorization header }, body: JSON.stringify({ childId: 'child-123', gameCode: 'schulte', completionTime: 45, score: 85 }) }); expect(response.status).toBe(401); }); test('should validate user has access to child', async () => { // Test with childId that doesn't belong to user const response = await fetch(`${BASE_URL}/api/mini-game/complete`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer test-token' }, body: JSON.stringify({ childId: 'other-user-child', gameCode: 'schulte', completionTime: 45, score: 85 }) }); expect(response.status).toBe(403); }); }); describe('Error Handling', () => { test('should handle database errors gracefully', async () => { // Test with invalid data that might cause DB error const response = await fetch(`${BASE_URL}/api/mini-game/complete`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer test-token' }, body: JSON.stringify({ childId: 'child-123', gameCode: 'schulte', completionTime: -1, // Invalid time score: -10 // Invalid score }) }); expect(response.status).toBe(400); }); test('should return meaningful error messages', async () => { const response = await fetch(`${BASE_URL}/api/mini-game/complete`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer test-token' }, body: JSON.stringify({ childId: '', gameCode: '', completionTime: 0, score: 0 }) }); const data = await response.json(); expect(data).toHaveProperty('message'); }); }); });