Skip to main content
Glama
grovesjosephn

Pokemon MCP Server

testDatabase.ts5.75 kB
import Database from 'better-sqlite3'; import { promises as fs } from 'fs'; import path from 'path'; /** * Test Database Helper for Ingestion Package * Creates a test database with the exact same schema as production. * This ensures tests use consistent schema and catch real-world issues. */ export class TestDatabase { private db: Database.Database; private dbPath: string; constructor(testName: string = 'ingestion-test') { // Create unique test database for each test suite with timestamp to avoid conflicts const timestamp = Date.now(); const randomId = Math.random().toString(36).substring(7); this.dbPath = path.join( process.cwd(), `${testName}-${timestamp}-${randomId}.sqlite` ); this.db = new Database(this.dbPath); this.setupProductionSchema(); } /** * Creates the exact same schema as production database * This is extracted from packages/pokemon-mcp-ingestion/src/database.ts */ private setupProductionSchema(): void { // Enable foreign keys (important for data integrity in tests) this.db.pragma('foreign_keys = ON'); // Create tables exactly as they exist in production this.db.exec(` CREATE TABLE IF NOT EXISTS pokemon ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, height INTEGER, weight INTEGER, base_experience INTEGER, generation INTEGER, species_url TEXT, sprite_url TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS stats ( id INTEGER PRIMARY KEY AUTOINCREMENT, pokemon_id INTEGER, stat_name TEXT, base_stat INTEGER, effort INTEGER, FOREIGN KEY (pokemon_id) REFERENCES pokemon (id) ); CREATE TABLE IF NOT EXISTS types ( id INTEGER PRIMARY KEY, name TEXT UNIQUE NOT NULL ); CREATE TABLE IF NOT EXISTS pokemon_types ( pokemon_id INTEGER, type_id INTEGER, slot INTEGER, PRIMARY KEY (pokemon_id, type_id), FOREIGN KEY (pokemon_id) REFERENCES pokemon (id), FOREIGN KEY (type_id) REFERENCES types (id) ); CREATE TABLE IF NOT EXISTS abilities ( id INTEGER PRIMARY KEY, name TEXT UNIQUE NOT NULL, is_hidden BOOLEAN DEFAULT FALSE ); CREATE TABLE IF NOT EXISTS pokemon_abilities ( pokemon_id INTEGER, ability_id INTEGER, is_hidden BOOLEAN DEFAULT FALSE, slot INTEGER, PRIMARY KEY (pokemon_id, ability_id), FOREIGN KEY (pokemon_id) REFERENCES pokemon (id), FOREIGN KEY (ability_id) REFERENCES abilities (id) ); CREATE TABLE IF NOT EXISTS moves ( id INTEGER PRIMARY KEY, name TEXT UNIQUE NOT NULL, power INTEGER, accuracy INTEGER, pp INTEGER, type_id INTEGER, damage_class TEXT, FOREIGN KEY (type_id) REFERENCES types (id) ); CREATE TABLE IF NOT EXISTS pokemon_moves ( pokemon_id INTEGER, move_id INTEGER, learn_method TEXT, level_learned INTEGER, PRIMARY KEY (pokemon_id, move_id, learn_method), FOREIGN KEY (pokemon_id) REFERENCES pokemon (id), FOREIGN KEY (move_id) REFERENCES moves (id) ); -- Performance indexes (same as production) CREATE INDEX IF NOT EXISTS idx_pokemon_name ON pokemon (name); CREATE INDEX IF NOT EXISTS idx_pokemon_generation ON pokemon (generation); CREATE INDEX IF NOT EXISTS idx_stats_pokemon ON stats (pokemon_id); CREATE INDEX IF NOT EXISTS idx_pokemon_types_pokemon ON pokemon_types (pokemon_id); `); } /** * Insert minimal test data for ingestion tests */ insertTestData(): void { // Insert basic types that might be referenced during ingestion const types = [ { id: 1, name: 'grass' }, { id: 2, name: 'poison' }, { id: 3, name: 'electric' }, { id: 4, name: 'psychic' }, ]; const insertType = this.db.prepare( 'INSERT OR IGNORE INTO types (id, name) VALUES (?, ?)' ); types.forEach((t) => insertType.run(t.id, t.name)); // Insert basic abilities that might be referenced during ingestion const abilities = [ { id: 1, name: 'overgrow' }, { id: 2, name: 'static' }, { id: 3, name: 'pressure' }, { id: 4, name: 'chlorophyll' }, { id: 5, name: 'lightning-rod' }, ]; const insertAbility = this.db.prepare( 'INSERT OR IGNORE INTO abilities (id, name) VALUES (?, ?)' ); abilities.forEach((a) => insertAbility.run(a.id, a.name)); } /** * Get the database instance for direct queries in tests */ getDatabase(): Database.Database { return this.db; } /** * Clean up - close database and delete file */ async cleanup(): Promise<void> { this.db.close(); try { await fs.unlink(this.dbPath); } catch { // File might not exist, that's okay } } /** * Clear all data from tables (useful for test isolation) */ clearData(): void { // Disable foreign keys temporarily for cascading deletes this.db.pragma('foreign_keys = OFF'); // Clear tables in dependency order this.db.exec(` DELETE FROM pokemon_moves; DELETE FROM moves; DELETE FROM pokemon_abilities; DELETE FROM abilities; DELETE FROM pokemon_types; DELETE FROM types; DELETE FROM stats; DELETE FROM pokemon; `); // Re-enable foreign keys this.db.pragma('foreign_keys = ON'); } } /** * Convenience function for creating test databases */ export function createTestDatabase(testName?: string): TestDatabase { return new TestDatabase(testName); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/grovesjosephn/pokemcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server