UNPKG

advanced-games-library

Version:

Advanced Gaming Library for React Native - Four Complete Games with iOS Compatibility Fixes

311 lines (243 loc) 10.3 kB
import { DefaultStorageService, MemoryStorage } from '../services/StorageService'; import { PlayerData, GameResult, GameDifficulty } from '../core/types'; // Mock AsyncStorage const mockAsyncStorage = { setItem: jest.fn(), getItem: jest.fn(), removeItem: jest.fn(), getAllKeys: jest.fn(), multiRemove: jest.fn(), clear: jest.fn() }; // Mock the import jest.mock('@react-native-async-storage/async-storage', () => mockAsyncStorage); describe('StorageService', () => { let storageService: DefaultStorageService; beforeEach(() => { storageService = new DefaultStorageService(); jest.clearAllMocks(); }); describe('Initialization', () => { it('should initialize with AsyncStorage', async () => { await expect(storageService.initialize()).resolves.not.toThrow(); }); }); describe('Player Data Storage', () => { const samplePlayerData: PlayerData = { playerId: 'test123', firstName: 'Test', lastName: 'User', age: 25, createdAt: new Date('2023-01-01'), lastActive: new Date('2023-01-02'), totalGamesPlayed: 5, achievements: [] }; it('should save player data', async () => { mockAsyncStorage.setItem.mockResolvedValue(undefined); await expect(storageService.savePlayerData(samplePlayerData)).resolves.not.toThrow(); expect(mockAsyncStorage.setItem).toHaveBeenCalledWith( '@games_library_player', JSON.stringify(samplePlayerData) ); }); it('should get player data', async () => { const storedData = JSON.stringify(samplePlayerData); mockAsyncStorage.getItem.mockResolvedValue(storedData); const result = await storageService.getPlayerData(); expect(result).not.toBeNull(); expect(result!.playerId).toBe('test123'); expect(result!.firstName).toBe('Test'); expect(result!.createdAt).toBeInstanceOf(Date); }); it('should return null when no player data exists', async () => { mockAsyncStorage.getItem.mockResolvedValue(null); const result = await storageService.getPlayerData(); expect(result).toBeNull(); }); it('should handle corrupted player data gracefully', async () => { mockAsyncStorage.getItem.mockResolvedValue('invalid json'); const result = await storageService.getPlayerData(); expect(result).toBeNull(); }); it('should clear player data', async () => { mockAsyncStorage.removeItem.mockResolvedValue(undefined); await expect(storageService.clearPlayerData()).resolves.not.toThrow(); expect(mockAsyncStorage.removeItem).toHaveBeenCalledWith('@games_library_player'); }); }); describe('Game Results Storage', () => { const sampleGameResult: GameResult = { gameId: 'memory-match', playerId: 'test123', score: 850, maxScore: 1000, timeSpent: 120000, completed: true, difficulty: GameDifficulty.MEDIUM, customData: { moves: 15 }, timestamp: new Date('2023-01-01'), sessionId: 'session123' }; it('should save game result', async () => { // Mock existing empty results mockAsyncStorage.getItem.mockResolvedValue('[]'); mockAsyncStorage.setItem.mockResolvedValue(undefined); await expect(storageService.saveGameResult(sampleGameResult)).resolves.not.toThrow(); expect(mockAsyncStorage.setItem).toHaveBeenCalled(); }); it('should append to existing game results', async () => { const existingResult: GameResult = { ...sampleGameResult, sessionId: 'session122' }; mockAsyncStorage.getItem.mockResolvedValue(JSON.stringify([existingResult])); mockAsyncStorage.setItem.mockResolvedValue(undefined); await storageService.saveGameResult(sampleGameResult); const setItemCall = mockAsyncStorage.setItem.mock.calls[0]; const savedData = JSON.parse(setItemCall[1]); expect(savedData).toHaveLength(2); }); it('should limit results to last 100', async () => { // Create 101 results const manyResults = Array.from({ length: 101 }, (_, i) => ({ ...sampleGameResult, sessionId: `session${i}` })); mockAsyncStorage.getItem.mockResolvedValue(JSON.stringify(manyResults)); mockAsyncStorage.setItem.mockResolvedValue(undefined); await storageService.saveGameResult(sampleGameResult); const setItemCall = mockAsyncStorage.setItem.mock.calls[0]; const savedData = JSON.parse(setItemCall[1]); expect(savedData).toHaveLength(100); }); it('should get game results', async () => { const results = [sampleGameResult]; mockAsyncStorage.getItem.mockResolvedValue(JSON.stringify(results)); const retrievedResults = await storageService.getGameResults(); expect(retrievedResults).toHaveLength(1); expect(retrievedResults[0].gameId).toBe('memory-match'); expect(retrievedResults[0].timestamp).toBeInstanceOf(Date); }); it('should filter results by player ID', async () => { const results = [ { ...sampleGameResult, playerId: 'player1' }, { ...sampleGameResult, playerId: 'player2' }, { ...sampleGameResult, playerId: 'player1' } ]; mockAsyncStorage.getItem.mockResolvedValue(JSON.stringify(results)); const filteredResults = await storageService.getGameResults('player1'); expect(filteredResults).toHaveLength(2); filteredResults.forEach(result => { expect(result.playerId).toBe('player1'); }); }); it('should return empty array when no results exist', async () => { mockAsyncStorage.getItem.mockResolvedValue(null); const results = await storageService.getGameResults(); expect(results).toEqual([]); }); it('should clear game results', async () => { mockAsyncStorage.removeItem.mockResolvedValue(undefined); await expect(storageService.clearGameResults()).resolves.not.toThrow(); expect(mockAsyncStorage.removeItem).toHaveBeenCalledWith('@games_library_results'); }); }); describe('Generic Data Storage', () => { it('should save and retrieve generic data', async () => { const testData = { test: 'value', number: 42 }; const testKey = 'test_key'; mockAsyncStorage.setItem.mockResolvedValue(undefined); mockAsyncStorage.getItem.mockResolvedValue(JSON.stringify(testData)); await storageService.saveData(testKey, testData); const retrievedData = await storageService.getData(testKey); expect(mockAsyncStorage.setItem).toHaveBeenCalledWith(testKey, JSON.stringify(testData)); expect(retrievedData).toEqual(testData); }); it('should remove data', async () => { const testKey = 'test_key'; mockAsyncStorage.removeItem.mockResolvedValue(undefined); await expect(storageService.removeData(testKey)).resolves.not.toThrow(); expect(mockAsyncStorage.removeItem).toHaveBeenCalledWith(testKey); }); it('should get all keys', async () => { const keys = ['key1', 'key2', '@games_library_player']; mockAsyncStorage.getAllKeys.mockResolvedValue(keys); const retrievedKeys = await storageService.getAllKeys(); expect(retrievedKeys).toEqual(keys); }); it('should clear all library data', async () => { const allKeys = ['key1', '@games_library_player', '@games_library_results', 'key2']; mockAsyncStorage.getAllKeys.mockResolvedValue(allKeys); mockAsyncStorage.multiRemove.mockResolvedValue(undefined); await storageService.clear(); expect(mockAsyncStorage.multiRemove).toHaveBeenCalledWith([ '@games_library_player', '@games_library_results' ]); }); }); describe('Error Handling', () => { it('should handle save errors', async () => { const playerData: PlayerData = { playerId: 'test123', firstName: 'Test', lastName: 'User', createdAt: new Date(), lastActive: new Date(), totalGamesPlayed: 0, achievements: [] }; mockAsyncStorage.setItem.mockRejectedValue(new Error('Storage full')); await expect(storageService.savePlayerData(playerData)).rejects.toThrow('Failed to save player data'); }); it('should handle retrieval errors', async () => { mockAsyncStorage.getItem.mockRejectedValue(new Error('Storage error')); const result = await storageService.getPlayerData(); expect(result).toBeNull(); }); }); }); describe('MemoryStorage', () => { let memoryStorage: MemoryStorage; beforeEach(() => { memoryStorage = new MemoryStorage(); }); it('should store and retrieve items', async () => { await memoryStorage.setItem('key1', 'value1'); const retrieved = await memoryStorage.getItem('key1'); expect(retrieved).toBe('value1'); }); it('should return null for non-existent keys', async () => { const retrieved = await memoryStorage.getItem('non-existent'); expect(retrieved).toBeNull(); }); it('should remove items', async () => { await memoryStorage.setItem('key1', 'value1'); await memoryStorage.removeItem('key1'); const retrieved = await memoryStorage.getItem('key1'); expect(retrieved).toBeNull(); }); it('should get all keys', async () => { await memoryStorage.setItem('key1', 'value1'); await memoryStorage.setItem('key2', 'value2'); const keys = await memoryStorage.getAllKeys(); expect(keys.sort()).toEqual(['key1', 'key2']); }); it('should remove multiple items', async () => { await memoryStorage.setItem('key1', 'value1'); await memoryStorage.setItem('key2', 'value2'); await memoryStorage.setItem('key3', 'value3'); await memoryStorage.multiRemove(['key1', 'key3']); expect(await memoryStorage.getItem('key1')).toBeNull(); expect(await memoryStorage.getItem('key2')).toBe('value2'); expect(await memoryStorage.getItem('key3')).toBeNull(); }); it('should clear all items', async () => { await memoryStorage.setItem('key1', 'value1'); await memoryStorage.setItem('key2', 'value2'); await memoryStorage.clear(); const keys = await memoryStorage.getAllKeys(); expect(keys).toHaveLength(0); }); });