File size: 7,496 Bytes
7428b13 1f2c086 7428b13 1f2c086 7428b13 1f2c086 7428b13 1f2c086 7428b13 a46ce65 7428b13 a6cd8d1 7428b13 |
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 |
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 { PicletInstance } from '../lib/db/schema';
describe('EncounterService', () => {
beforeEach(async () => {
// Clear all data before each test
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 picletCount = await db.picletInstances.count();
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 (uncaught)
const testPiclet: Omit<PicletInstance, 'id'> = {
typeId: 'test-piclet',
nickname: 'Test Piclet',
primaryType: 'beast' as any,
currentHp: 100,
maxHp: 100,
level: 5,
xp: 0,
attack: 50,
defense: 50,
fieldAttack: 40,
fieldDefense: 40,
speed: 50,
baseHp: 100,
baseAttack: 50,
baseDefense: 50,
baseFieldAttack: 40,
baseFieldDefense: 40,
baseSpeed: 50,
moves: [],
nature: 'hardy',
specialAbility: { name: 'Test', description: 'Test', trigger: 'onBattleStart', effects: [] },
specialAbilityUnlockLevel: 1,
isInRoster: false,
caught: false,
bst: 300,
tier: 'low',
role: 'balanced',
variance: 0,
imageUrl: 'https://test.com/piclet.png',
imageCaption: 'test caption',
concept: 'test',
description: 'A test piclet',
imagePrompt: 'test prompt'
};
await db.picletInstances.add(testPiclet);
// 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);
});
});
}); |