-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun_tests.js
More file actions
342 lines (283 loc) · 11.9 KB
/
run_tests.js
File metadata and controls
342 lines (283 loc) · 11.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/**
* Simple test runner for HTML-based tests
* Runs tests in a headless browser environment using Node.js
*/
const fs = require('fs');
const path = require('path');
// Mock browser environment for Node.js
global.window = global;
global.document = {
addEventListener: () => {},
getElementById: () => null,
createElement: () => ({ style: {}, addEventListener: () => {} }),
head: { appendChild: () => {} },
body: { appendChild: () => {} }
};
global.performance = { now: () => Date.now() };
global.requestAnimationFrame = (callback) => setTimeout(callback, 16);
// Load game modules
const gameModules = [
'js/mazeGraph.js',
'js/pacman.js',
'js/ghost.js',
'js/ghostAI.js',
'js/inputHandler.js',
'js/renderer.js',
'js/gameEngine.js'
];
console.log('Loading game modules...');
// Mock canvas context for testing
const mockCanvas = {
width: 800,
height: 600,
getContext: () => ({
fillStyle: '',
strokeStyle: '',
lineWidth: 1,
globalAlpha: 1,
shadowColor: '',
shadowBlur: 0,
font: '',
textAlign: '',
imageSmoothingEnabled: false,
fillRect: () => {},
strokeRect: () => {},
beginPath: () => {},
moveTo: () => {},
lineTo: () => {},
arc: () => {},
fill: () => {},
stroke: () => {},
closePath: () => {},
fillText: () => {},
setLineDash: () => {}
})
};
// Load and execute each module
gameModules.forEach(modulePath => {
try {
if (fs.existsSync(modulePath)) {
const moduleCode = fs.readFileSync(modulePath, 'utf8');
eval(moduleCode);
console.log(`✓ Loaded ${modulePath}`);
} else {
console.log(`✗ Missing ${modulePath}`);
}
} catch (error) {
console.log(`✗ Error loading ${modulePath}: ${error.message}`);
}
});
console.log('\n=== Running Core System Tests ===\n');
let testsPassed = 0;
let totalTests = 0;
function test(name, condition) {
totalTests++;
if (condition) {
testsPassed++;
console.log(`✓ ${name}`);
return true;
} else {
console.log(`✗ ${name}`);
return false;
}
}
// Test 1: Module Loading
console.log('1. Module Loading Tests:');
test('MazeGraph class available', typeof MazeGraph === 'function');
test('PacMan class available', typeof PacMan === 'function');
test('Ghost class available', typeof Ghost === 'function');
test('GhostAI class available', typeof GhostAI === 'function');
test('GameEngine class available', typeof GameEngine === 'function');
test('InputHandler class available', typeof InputHandler === 'function');
test('Renderer class available', typeof Renderer === 'function');
// Test 2: MazeGraph System
console.log('\n2. MazeGraph System Tests:');
try {
const maze = new MazeGraph(20, 15);
test('MazeGraph constructor works', maze !== null);
test('MazeGraph has correct dimensions', maze.width === 20 && maze.height === 15);
test('MazeGraph initializes empty tiles', maze.getAllEmpty().length > 0);
maze.setTileType(5, 5, maze.TILE_TYPES.WALL);
test('Can set wall tiles', maze.getTileType(5, 5) === 'wall');
test('Wall tiles are not walkable', !maze.isWalkable(5, 5));
const created = maze.createDemoMaze();
test('Demo maze creation succeeds', created === true);
test('Demo maze has walls', maze.getAllWalls().length > 0);
test('Demo maze has pellets', maze.getPelletCount() > 0);
test('Demo maze has power pellets', maze.getPowerPelletCount() > 0);
const path = maze.findPathBFS(1, 1, 5, 5);
test('BFS pathfinding returns array', Array.isArray(path));
const pathAStar = maze.findPathAStar(1, 1, 5, 5);
test('A* pathfinding returns array', Array.isArray(pathAStar));
} catch (error) {
test('MazeGraph basic functionality', false);
console.log(` Error: ${error.message}`);
}
// Test 3: PacMan Entity
console.log('\n3. PacMan Entity Tests:');
try {
const pacman = new PacMan(10, 10);
test('PacMan constructor works', pacman !== null);
test('PacMan has correct initial position', pacman.position.x === 10 && pacman.position.y === 10);
test('PacMan starts with no direction', pacman.direction.name === 'none');
pacman.setPosition(15, 12);
test('Can set PacMan position', pacman.position.x === 15 && pacman.position.y === 12);
const history = pacman.getMovementHistory();
test('Movement history is array', Array.isArray(history));
const predicted = pacman.getPredictedPosition(4);
test('Predicted position calculation works', predicted && typeof predicted.x === 'number');
} catch (error) {
test('PacMan basic functionality', false);
console.log(` Error: ${error.message}`);
}
// Test 4: Ghost AI System
console.log('\n4. Ghost AI System Tests:');
try {
const ghostAI = new GhostAI();
const maze = new MazeGraph(20, 15);
maze.createDemoMaze();
test('GhostAI constructor works', ghostAI !== null);
const ghostConfigs = [
{ x: 5, y: 5, color: 'red', personality: 'aggressive' },
{ x: 15, y: 5, color: 'pink', personality: 'ambush' },
{ x: 15, y: 10, color: 'cyan', personality: 'patrol' },
{ x: 5, y: 10, color: 'orange', personality: 'random' }
];
ghostAI.initializeGhosts(ghostConfigs, maze);
const ghosts = ghostAI.getGhosts();
test('Correct number of ghosts initialized', ghosts.length === 4);
test('Ghosts have correct colors',
ghosts[0].color === 'red' &&
ghosts[1].color === 'pink' &&
ghosts[2].color === 'cyan' &&
ghosts[3].color === 'orange');
test('Ghosts have correct personalities',
ghosts[0].personality === 'aggressive' &&
ghosts[1].personality === 'ambush' &&
ghosts[2].personality === 'patrol' &&
ghosts[3].personality === 'random');
const redGhost = ghosts[0];
test('Ghost starts in scatter state', redGhost.currentState === 'scatter');
test('Ghost has state configuration', redGhost.stateConfig && typeof redGhost.stateConfig === 'object');
const pacman = new PacMan(10, 7);
const gameState = {
powerPelletActive: false,
powerPelletTimer: 0,
score: 0,
lives: 3,
level: 1
};
ghostAI.update(16.67, pacman, maze, gameState);
test('AI update completes without error', true);
const collisions = ghostAI.checkCollisions(pacman);
test('Collision detection returns array', Array.isArray(collisions));
const metrics = ghostAI.getPerformanceMetrics();
test('Performance metrics available', metrics && typeof metrics.lastUpdateTime === 'number');
} catch (error) {
test('GhostAI basic functionality', false);
console.log(` Error: ${error.message}`);
}
// Test 5: Game Engine Integration
console.log('\n5. Game Engine Integration Tests:');
try {
const gameEngine = new GameEngine(mockCanvas);
test('GameEngine constructor works', gameEngine !== null);
test('GameEngine has canvas reference', gameEngine.canvas === mockCanvas);
test('GameEngine has initial game state', gameEngine.gameState && typeof gameEngine.gameState === 'object');
const maze = new MazeGraph(20, 15);
maze.createDemoMaze();
const inputHandler = new InputHandler();
gameEngine.initializeEntities(inputHandler, maze);
test('PacMan entity created', gameEngine.getPacMan() !== null);
test('Ghosts created', gameEngine.getGhosts().length > 0);
test('GhostAI system created', gameEngine.getGhostAI() !== null);
const initialScore = gameEngine.gameState.score;
gameEngine.addScore(100);
test('Score system works', gameEngine.gameState.score === initialScore + 100);
gameEngine.activatePowerPellet(5000);
test('Power pellet activation works', gameEngine.gameState.powerPelletActive === true);
const metrics = gameEngine.getPerformanceMetrics();
test('Performance metrics available', metrics && typeof metrics === 'object');
} catch (error) {
test('GameEngine basic functionality', false);
console.log(` Error: ${error.message}`);
}
// Test 6: Collision Detection
console.log('\n6. Collision Detection Tests:');
try {
const pacman = new PacMan(10, 10);
const ghost = new Ghost(10, 10, 'red', 'aggressive');
test('Collision detected at same position', ghost.checkCollisionWithPacman(pacman));
ghost.setPosition(15, 15);
test('No collision when far apart', !ghost.checkCollisionWithPacman(pacman));
ghost.setPosition(10.3, 10.3);
test('Collision detected within radius', ghost.checkCollisionWithPacman(pacman));
const ghostAI = new GhostAI();
const maze = new MazeGraph(20, 15);
maze.createDemoMaze();
const ghostConfigs = [
{ x: 10, y: 10, color: 'red', personality: 'aggressive' },
{ x: 15, y: 10, color: 'pink', personality: 'ambush' }
];
ghostAI.initializeGhosts(ghostConfigs, maze);
const collisions = ghostAI.checkCollisions(pacman);
test('GhostAI collision detection works', Array.isArray(collisions));
test('Collision detected with overlapping ghost', collisions.length > 0);
} catch (error) {
test('Collision detection functionality', false);
console.log(` Error: ${error.message}`);
}
// Test 7: Input Handling
console.log('\n7. Input Handling Tests:');
try {
const inputHandler = new InputHandler();
test('InputHandler constructor works', inputHandler !== null);
test('InputHandler has direction mappings', inputHandler.directions && typeof inputHandler.directions === 'object');
test('InputHandler starts with no direction', inputHandler.currentDirection.name === 'none');
const testDirection = { x: 1, y: 0, name: 'right' };
inputHandler.setCurrentDirection(testDirection);
test('Can set current direction', inputHandler.getCurrentDirection().name === 'right');
const inputState = inputHandler.getInputState();
test('Input state available', inputState && typeof inputState === 'object');
inputHandler.reset();
test('Input handler reset works', inputHandler.getCurrentDirection().name === 'none');
} catch (error) {
test('Input handling functionality', false);
console.log(` Error: ${error.message}`);
}
// Test 8: Rendering System
console.log('\n8. Rendering System Tests:');
try {
const renderer = new Renderer(mockCanvas, mockCanvas.getContext('2d'));
test('Renderer constructor works', renderer !== null);
test('Renderer has canvas reference', renderer.canvas === mockCanvas);
test('Renderer has color palette', renderer.colors && typeof renderer.colors === 'object');
renderer.clear();
test('Canvas clear operation works', true);
const maze = new MazeGraph(20, 15);
maze.createDemoMaze();
renderer.drawMaze(maze);
test('Maze rendering completes', true);
renderer.drawPacMan(10, 10, { name: 'right' }, 0);
test('PacMan rendering completes', true);
renderer.drawGhost(5, 5, '#ff0000', 'chase', 0);
test('Ghost rendering completes', true);
const initialFrame = renderer.animationFrame;
renderer.updateAnimation();
test('Animation update works', renderer.animationFrame > initialFrame);
} catch (error) {
test('Rendering system functionality', false);
console.log(` Error: ${error.message}`);
}
// Summary
console.log('\n=== Test Summary ===');
const passRate = ((testsPassed / totalTests) * 100).toFixed(1);
console.log(`Tests passed: ${testsPassed}/${totalTests} (${passRate}%)`);
if (passRate >= 90) {
console.log('✓ CHECKPOINT 8 PASSED - Core AI and gameplay mechanics are working correctly!');
} else if (passRate >= 75) {
console.log('⚠ CHECKPOINT 8 PARTIAL - Most systems working, some issues need attention');
} else {
console.log('✗ CHECKPOINT 8 FAILED - Significant issues need to be resolved');
}
console.log('\nCheckpoint 8 validation complete.');