import { describe, it, expect, beforeEach } from 'vitest';
import Database from 'better-sqlite3';
import { SearchPokemonTool } from '../../src/tools/searchPokemon.js';
describe('SearchPokemonTool', () => {
let db: Database.Database;
let tool: SearchPokemonTool;
beforeEach(() => {
// Create an in-memory database for testing
db = new Database(':memory:');
// Create necessary tables
db.exec(`
CREATE TABLE pokemon (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
height INTEGER NOT NULL,
weight INTEGER NOT NULL,
base_experience INTEGER NOT NULL,
generation INTEGER NOT NULL,
species_url TEXT NOT NULL,
sprite_url TEXT NOT NULL
);
CREATE TABLE types (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE pokemon_types (
pokemon_id INTEGER NOT NULL,
type_id INTEGER NOT NULL,
slot INTEGER NOT NULL,
FOREIGN KEY (pokemon_id) REFERENCES pokemon(id),
FOREIGN KEY (type_id) REFERENCES types(id)
);
CREATE TABLE stats (
pokemon_id INTEGER NOT NULL,
stat_name TEXT NOT NULL,
base_stat INTEGER NOT NULL,
effort INTEGER NOT NULL,
FOREIGN KEY (pokemon_id) REFERENCES pokemon(id)
);
`);
// Insert test data
db.exec(`
INSERT INTO pokemon (id, name, height, weight, base_experience, generation, species_url, sprite_url)
VALUES
(1, 'bulbasaur', 7, 69, 64, 1, 'https://pokeapi.co/api/v2/pokemon-species/1/', 'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/1.png'),
(4, 'charmander', 6, 85, 62, 1, 'https://pokeapi.co/api/v2/pokemon-species/4/', 'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/4.png'),
(7, 'squirtle', 5, 90, 63, 1, 'https://pokeapi.co/api/v2/pokemon-species/7/', 'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/7.png');
INSERT INTO types (id, name) VALUES
(1, 'grass'),
(2, 'poison'),
(3, 'fire'),
(4, 'water');
INSERT INTO pokemon_types (pokemon_id, type_id, slot) VALUES
(1, 1, 1), (1, 2, 2),
(4, 3, 1),
(7, 4, 1);
INSERT INTO stats (pokemon_id, stat_name, base_stat, effort)
VALUES
(1, 'hp', 45, 0),
(1, 'attack', 49, 0),
(1, 'defense', 49, 0),
(1, 'special-attack', 65, 1),
(1, 'special-defense', 65, 0),
(1, 'speed', 45, 0),
(4, 'hp', 39, 0),
(4, 'attack', 52, 0),
(4, 'defense', 43, 0),
(4, 'special-attack', 60, 0),
(4, 'special-defense', 50, 0),
(4, 'speed', 65, 1),
(7, 'hp', 44, 0),
(7, 'attack', 48, 0),
(7, 'defense', 65, 1),
(7, 'special-attack', 50, 0),
(7, 'special-defense', 64, 0),
(7, 'speed', 43, 0);
`);
tool = new SearchPokemonTool(db);
});
it('should return all Pokemon when no filters are applied', async () => {
const result = await tool.execute({});
expect(result.content[0].text).toContain('Bulbasaur');
expect(result.content[0].text).toContain('Charmander');
expect(result.content[0].text).toContain('Squirtle');
});
it('should filter by type', async () => {
const result = await tool.execute({ type: 'fire' });
expect(result.content[0].text).toContain('Charmander');
expect(result.content[0].text).not.toContain('Bulbasaur');
expect(result.content[0].text).not.toContain('Squirtle');
});
it('should filter by generation', async () => {
const result = await tool.execute({ generation: 1 });
expect(result.content[0].text).toContain('Bulbasaur');
expect(result.content[0].text).toContain('Charmander');
expect(result.content[0].text).toContain('Squirtle');
});
it('should filter by minimum stats', async () => {
const result = await tool.execute({ min_stat: 300 });
expect(result.content[0].text).toContain('Bulbasaur');
expect(result.content[0].text).toContain('Charmander');
expect(result.content[0].text).toContain('Squirtle');
});
it('should respect the limit parameter', async () => {
const result = await tool.execute({ limit: 2 });
const lines = result.content[0].text.split('\n');
const pokemonLines = lines.filter((line) => line.startsWith('**'));
expect(pokemonLines.length).toBe(2);
});
it('should return no results message when no matches found', async () => {
const result = await tool.execute({ type: 'dragon' });
expect(result.content[0].text).toBe(
'❌ **Error:** No Pokemon found matching the criteria.'
);
});
});