piclets / src /tests /encounterService.test.ts
Fraser's picture
alll working??
a6cd8d1
import { describe, it, expect, beforeEach } from 'vitest';
import { EncounterService } from '../lib/db/encounterService';
import { db } from '../lib/db';
import { EncounterType } from '../lib/db/schema';
import type { Monster, PicletInstance } from '../lib/db/schema';
describe('EncounterService', () => {
beforeEach(async () => {
// Clear all data before each test
await db.monsters.clear();
await db.picletInstances.clear();
await db.encounters.clear();
await db.gameState.clear();
});
describe('generateEncounters', () => {
it('should return empty array when no piclets are discovered', async () => {
// Arrange - ensure database is empty
const monsterCount = await db.monsters.count();
const picletCount = await db.picletInstances.count();
expect(monsterCount).toBe(0);
expect(picletCount).toBe(0);
// Act
const encounters = await EncounterService.generateEncounters();
// Assert
expect(encounters).toHaveLength(0);
// Verify encounters table is also empty
const dbEncounters = await db.encounters.toArray();
expect(dbEncounters).toHaveLength(0);
});
it('should return only "Your First Piclet!" when piclets are discovered but not caught', async () => {
// Arrange - add a discovered piclet (monster)
const testMonster: Omit<Monster, 'id'> = {
name: 'Test Piclet',
imageUrl: 'https://test.com/piclet.png',
concept: 'test',
imagePrompt: 'test prompt',
imageCaption: 'test caption',
createdAt: new Date()
};
await db.monsters.add(testMonster);
// Act
const encounters = await EncounterService.generateEncounters();
// Assert
expect(encounters).toHaveLength(1);
expect(encounters[0].type).toBe(EncounterType.WILD_PICLET);
expect(encounters[0].title).toBe('Your First Piclet!');
expect(encounters[0].description).toBe('A friendly piclet appears! This one seems easy to catch.');
expect(encounters[0].enemyLevel).toBe(5);
});
it('should return shop, health center, and wild encounters when player has caught piclets', async () => {
// Arrange - add a caught piclet
const testPiclet: Omit<PicletInstance, 'id'> = {
typeId: 'test-001',
nickname: 'Testy',
primaryType: 'beast' as any,
level: 5,
xp: 0,
currentHp: 20,
maxHp: 20,
attack: 10,
defense: 10,
fieldAttack: 10,
fieldDefense: 10,
speed: 10,
baseHp: 20,
baseAttack: 10,
baseDefense: 10,
baseFieldAttack: 10,
baseFieldDefense: 10,
baseSpeed: 10,
moves: [],
nature: 'hardy',
isInRoster: true,
rosterPosition: 0,
caughtAt: new Date(),
bst: 60,
tier: 'common',
role: 'balanced',
variance: 1,
imageUrl: 'https://test.com/piclet.png',
imageCaption: 'Test',
concept: 'test',
imagePrompt: 'test'
};
await db.picletInstances.add(testPiclet);
// Add some discovered monsters so wild encounters can be generated
const testMonster = {
name: 'Test Monster',
imageUrl: 'https://test.com/monster.png',
imageCaption: 'A test monster',
concept: 'test concept',
imagePrompt: 'test prompt',
createdAt: new Date()
};
await db.monsters.add(testMonster);
// Act
const encounters = await EncounterService.generateEncounters();
// Assert
expect(encounters.length).toBeGreaterThanOrEqual(4); // At least shop, health center, and 2 wild
// Check for required encounter types
const encounterTypes = encounters.map(e => e.type);
expect(encounterTypes).toContain(EncounterType.SHOP);
expect(encounterTypes).toContain(EncounterType.HEALTH_CENTER);
// Count wild encounters
const wildCount = encounters.filter(e => e.type === EncounterType.WILD_PICLET).length;
expect(wildCount).toBeGreaterThanOrEqual(2);
expect(wildCount).toBeLessThanOrEqual(3);
// Verify shop encounter details
const shopEncounter = encounters.find(e => e.type === EncounterType.SHOP);
expect(shopEncounter?.title).toBe('Piclet Shop');
// Verify health center encounter details
const healthEncounter = encounters.find(e => e.type === EncounterType.HEALTH_CENTER);
expect(healthEncounter?.title).toBe('Health Center');
});
it('should not include shop/health center with first catch encounter', async () => {
// Arrange - add only a discovered piclet, no caught piclets
await db.monsters.add({
name: 'Discovered Piclet',
imageUrl: 'https://test.com/discovered.png',
concept: 'discovered',
imagePrompt: 'discovered prompt',
imageCaption: 'discovered caption',
createdAt: new Date()
});
// Ensure no caught piclets
const caughtCount = await db.picletInstances.count();
expect(caughtCount).toBe(0);
// Act
const encounters = await EncounterService.generateEncounters();
// Assert - should only have the first catch encounter
expect(encounters).toHaveLength(1);
expect(encounters[0].title).toBe('Your First Piclet!');
// Should NOT have shop or health center
const hasShop = encounters.some(e => e.type === EncounterType.SHOP);
const hasHealthCenter = encounters.some(e => e.type === EncounterType.HEALTH_CENTER);
expect(hasShop).toBe(false);
expect(hasHealthCenter).toBe(false);
});
});
describe('shouldRefreshEncounters', () => {
it('should return true after 2 hours', async () => {
// Arrange - create game state with old refresh time
const twoHoursAgo = new Date(Date.now() - (2.5 * 60 * 60 * 1000));
await db.gameState.add({
lastEncounterRefresh: twoHoursAgo,
lastPlayed: new Date(),
progressPoints: 0,
trainersDefeated: 0,
picletsCapured: 0,
battlesLost: 0
});
// Act
const shouldRefresh = await EncounterService.shouldRefreshEncounters();
// Assert
expect(shouldRefresh).toBe(true);
});
it('should return false within 2 hours', async () => {
// Arrange - create game state with recent refresh time
const oneHourAgo = new Date(Date.now() - (1 * 60 * 60 * 1000));
await db.gameState.add({
lastEncounterRefresh: oneHourAgo,
lastPlayed: new Date(),
progressPoints: 0,
trainersDefeated: 0,
picletsCapured: 0,
battlesLost: 0
});
// Act
const shouldRefresh = await EncounterService.shouldRefreshEncounters();
// Assert
expect(shouldRefresh).toBe(false);
});
});
});